如何将多个Git提交(已推送)还原到已发布的存储库?

时间:2012-05-28 06:27:50

标签: git version-control

git的新手,已经搞砸了。

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

我在想这样做:

  1. 创建一个名为“measured-thing”的本地分支
  2. 将本地存储库还原到其工作状态(希望有意义的提交有帮助);
  3. 推送到远程

  4. 完成对测试对象的测试

  5. 合并“已测试的东西”进入开发
  6. 推送到远程
  7. 在第3步和第5步之间,其他开发人员可能会提交并推送,我担心这可能导致“合并悲剧” - 无论如何,这可能是一种正确的方法吗?

    更新

    这里的主要问题在于2)

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

    他们建议:

    1. $ git branch test
    2. $ git reset --hard a6b4c974
    3. 通过这样做,其他开发人员仍然可以:

      $ git commit(在开发分支上)

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

      尽管你有各种各样的选择,但感觉这是一个很好的方法。 但是,如果在我们推动之后可以做到这一点,就没有说明了吗?

      请注意以下内容:由于我做了这些更改并且搞砸了所有内容,到目前为止还没有其他人在存储库上工作。所以,如果我还原工作目录,没有人会注意到。

3 个答案:

答案 0 :(得分:117)

问题

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

已发布分支的解决方案

您概述的步骤具有优点。如果您需要dev分支立即保持稳定,那就这样做吧。您有Debugging with 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 ninjas才能查看或恢复您错误提交的提交。

答案 1 :(得分:27)

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

请勿使用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等工具以一致的方式自动创建分支。

答案 2 :(得分:0)

git revert HEAD -m 1

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

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

  

git reset --hard siriwjdd