93

git新手,已经搞砸了。

我已经提交并将一些更改推送到远程开发机器。我需要恢复旧版本,但要保持“糟糕的进展”,以继续在单独的分支上工作;

我在想这样做:

  1. 创建一个名为:“tested-thing”的本地分支
  2. 将本地存储库恢复到它工作的状态(希望有意义的提交会有所帮助)
  3. 推送到远程

  4. 完成测试事物的测试

  5. 将“测试的东西”合并到开发中
  6. 推送到远程

在第 3 步和第 5 步之间,其他开发人员可能会提交和推送,恐怕这可能会导致“合并悲剧” - 无论如何,这可能是正确的方法吗?

更新:

这里的主要问题在于2)

在这里,关于主题:“将工作分解为主题分支” http://learn.github.com/p/undoing.html

他们建议:

  1. $ git 分支测试
  2. $ git reset --hard a6b4c974

通过这样做,其他开发人员仍然可以:

$ git commit(在开发分支上)

我可以结帐以测试并解决它,直到合并时间。

尽管您有所有选择,但这感觉是一种很好的方法。但是,没有说明在我们推送之后是否可以这样做?

请注意以下几点:由于我进行了这些更改并且我搞砸了所有事情,所以到目前为止没有其他人在存储库上工作过。所以,如果我恢复工作目录,没有人会注意到。

4

3 回答 3

164

问题

您可以使用许多工作流程。要点是不要在已发布的分支中破坏历史记录,除非您已与可能使用该分支并愿意对每个人的克隆进行手术的每个人进行了沟通。如果可以避免,最好不要这样做。

已发布分支的解决方案

您概述的步骤有优点。如果您需要 dev 分支立即稳定,请这样做。您有许多使用 Git 进行调试的工具,它们将帮助您找到正确的分支点,然后您可以恢复上次稳定提交和 HEAD 之间的所有提交。

以相反的顺序一次还原提交一个,或使用<first_bad_commit>..<last_bad_commit>范围。哈希是指定提交范围的最简单方法,但还有其他表示法。例如,如果您推送了 5 个错误提交,您可以使用以下命令恢复它们:

# Revert a series using ancestor notation.
git revert --no-edit dev~5..dev

# Revert a series using commit hashes.
git revert --no-edit ffffffff..12345678

这将按顺序将反向补丁应用到您的工作目录,反向工作到您的已知良好提交。使用--no-edit标志,在应用每个反向补丁后,将自动提交对工作目录的更改。

有关man 1 git-revert更多选项,以及man 7 gitrevisions指定要恢复的提交的不同方法,请参阅。

或者,您可以分支您的 HEAD,按照需要的方式修复问题,然后重新合并。与此同时,您的构建将被破坏,但这在某些情况下可能是有意义的。

危险地带

当然,如果您绝对确定自从您的错误推送以来没有人从存储库中拉出,并且如果远程是一个裸存储库,那么您可以执行非快进提交。

git reset --hard <last_good_commit>
git push --force

这将使您的系统和上游主机上的 reflog 保持完整,但您的错误提交将从可直接访问的历史记录中消失,并且不会在拉取时传播。您的旧更改将一直保留,直到存储库被修剪,但只有 Git 忍者才能看到或恢复您错误地提交。

于 2012-05-28T06:51:01.930 回答
35

如果您已经将内容推送到远程服务器(并且您有其他开发人员在同一个远程分支上工作),那么要记住的重要一点是您不想重写历史记录

不要使用 git reset --hard

您需要还原更改,否则任何在其历史记录中已删除提交的签出都将在下次推送时将它们添加回远程存储库;并且任何其他结帐将在此后的下一次拉动中将它们拉入。

如果您尚未将更改推送到遥控器,则可以使用

git reset --hard <hash>

如果您推送更改,但确定没有人拉取更改,您可以使用

git reset --hard
git push -f

如果您推送更改,并且有人将其拉入结帐,您仍然可以这样做,但其他团队成员/结帐需要协作:

(you) git reset --hard <hash>
(you) git push -f

(them) git fetch
(them) git reset --hard origin/branch

但总的来说,这会变成一团糟。所以,还原:

要删除的提交是最新的

这可能是最常见的情况,你做了一些事情——你把它们推出来,然后意识到它们不应该存在。

首先,您需要确定要返回的提交,您可以这样做:

git log

只需在更改之前查找提交,并注意提交哈希。-n您可以使用以下标志将日志限制为最近的提交:git log -n 5

然后将您的分支重置为您希望其他开发人员看到的状态:

git revert  <hash of first borked commit>..HEAD

最后一步是创建您自己的本地分支以重新应用您恢复的更改:

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .

继续工作my-new-branch直到完成,然后将其合并到您的主要开发分支中。

要删除的提交与其他提交混合在一起

如果您要还原的提交不是全部在一起,那么单独还原它们可能是最简单的。再次使用git log查找要删除的提交,然后:

git revert <hash>
git revert <another hash>
..

然后,再次创建您的分支以继续您的工作:

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .

再一次,当你完成时,破解并合并。

你应该最终得到一个看起来像这样的提交历史my-new-branch

2012-05-28 10:11 AD7six             o [my-new-branch] Revert "Revert "another mistake""
2012-05-28 10:11 AD7six             o Revert "Revert "committing a mistake""
2012-05-28 10:09 AD7six             o [master] Revert "committing a mistake"
2012-05-28 10:09 AD7six             o Revert "another mistake"
2012-05-28 10:08 AD7six             o another mistake
2012-05-28 10:08 AD7six             o committing a mistake
2012-05-28 10:05 Bob                I XYZ nearly works

更好的方式®

尤其是现在您已经意识到多个开发人员在同一个分支中工作的危险,请考虑始终在您的工作中使用功能分支。这意味着在分支中工作直到完成某些事情,然后才将其合并到您的主分支。还可以考虑使用git-flow等工具以一致的方式自动创建分支。

于 2012-05-28T07:51:33.193 回答
-2
git revert HEAD -m 1

在上面的代码行中。“最后一个参数代表”

  • 1 - 恢复一个提交。2 - 恢复上次提交。n - 恢复最后 n 次提交

或者

git reset --hard siriwjdd

于 2015-08-20T14:38:10.243 回答