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

MEM*_*MEM 66 git version-control

git的新手,已经搞砸了.

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

我在想这样做:

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

  4. 完成对测试物的测试

  5. "被测试的东西" 合并到开发中
  6. 推送到远程

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

更新:

这里的主要问题在于2)

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

他们建议:

  1. $ git branch test
  2. $ git reset --hard a6b4c974

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

$ git commit (在开发分支上)

我可以结账测试并解决它直到合并时间.

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

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

Tod*_*obs 130

问题

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

已发布分支的解决方案

您概述的步骤具有优点.如果您需要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
Run Code Online (Sandbox Code Playgroud)

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

有关man 1 git-revert更多选项以及man 7 gitrevisions指定要还原的提交的不同方法,请参阅参考资料.

或者,您可以分离HEAD,按照需要的方式修复问题,然后重新合并.在此期间你的构建将被打破,但在某些情况下这可能是有意义的.

危险区

当然,如果您完全确定没有人因为您的错误推送而从存储库中撤出,并且如果远程服务器是裸存储库,那么您可以执行非快进提交.

git reset --hard <last_good_commit>
git push --force
Run Code Online (Sandbox Code Playgroud)

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

  • 如果您使用的是提交标签,则不是`&lt;first_bad_commit&gt;`.. &lt;last_bad_commit&gt;`,而是&lt;last_good_commit&gt; .. &lt;last_bad_commit&gt; (2认同)

AD7*_*six 29

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

不要使用git reset --hard

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

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

git reset --hard <hash>
Run Code Online (Sandbox Code Playgroud)

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

git reset --hard
git push -f
Run Code Online (Sandbox Code Playgroud)

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

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

(them) git fetch
(them) git reset --hard origin/branch
Run Code Online (Sandbox Code Playgroud)

但总的来说,这变得一团糟.所以,还原:

删除的承诺是最新的

这可能是最常见的情况,你已经做了一些事情 - 你已经推出它们然后意识到它们不应该存在.

首先,您需要确定要返回的提交,您可以通过以下方式执行此操作:

git log
Run Code Online (Sandbox Code Playgroud)

只需在更改之前查找提交,并记下提交哈希.您可以使用-n标志将日志限制为最多重新提交:git log -n 5

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

git revert  <hash of first borked commit>..HEAD
Run Code Online (Sandbox Code Playgroud)

最后一步是创建您自己的本地分支,重新应用您还原的更改:

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Run Code Online (Sandbox Code Playgroud)

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

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

如果你想要恢复的提交不是全部,那么单独恢复它们可能是最容易的.再次使用git logfind你要删除的提交,然后:

git revert <hash>
git revert <another hash>
..
Run Code Online (Sandbox Code Playgroud)

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

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Run Code Online (Sandbox Code Playgroud)

然后,当你完成后,再次攻击并合并.

您应该最终得到一个类似于此的提交历史记录 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
Run Code Online (Sandbox Code Playgroud)

更好的方式®

特别是现在您已经意识到在同一分支中工作的几个开发人员的危险,请考虑始终为您的工作使用功能分支.所有这些意味着在一个分支中工作,直到某些东西完成,然后才将它合并到你的主分支.还要考虑使用git-flow等工具以一致的方式自动创建分支.