如何“取消还原”已还原的Git提交?


483

给定已使用进行更改,commit然后使用还原的更改,revert撤消该还原的最佳方法是什么?

理想情况下,应该使用新的提交完成此操作,以免重写历史记录。



@phuclv此处有可能重复的评论,请指向此处。一个必须注明原件及必须标明dupliate
约翰DEMETRIOU

@JohnDemetriou没有开放答案的问题。时间与这里无关紧要如何处理重复的问题?
phuclv

我没有说时间。我只是在评论关于此问题的两个问题之一
John Demetriou

Answers:


384

如果您尚未推动更改, git reset --hard HEAD^

否则,还原还原就可以了。

另一种方法是git checkout HEAD^^ -- .,然后git add -A && git commit


8
请注意,如果您要取消还原而没有立即将原始更改应用于master分支,则可以(1)还原后删除原始分支,(2)按Adam指出的在还原分支上单击“还原” ,然后( 3)在结果PR的标题中单击“编辑”,然后将目标分支更改为原始分支,而不是主分支。现在,您的原始分支可以重新合并以实现以前还原的更改。
pauljm 2014年

1
请注意,这将删除工作树和索引中的所有更改。使用git stash保存任何您不会丢失的更改。
zpon

3
checkout && commit方法的优点是什么?在一般情况下git cherry-pick或替代情况下,似乎是git revert还原还原的最直接方法。
罗伯特·杰克·威尔

5
我认为这将有助于显示如何:Otherwise, reverting the revert is perfectly fine.,然后解释git checkout HEAD^^ -- .正在做什么。
托德(Todd),

3
上帝,不要使用git add -A...除非您要将每个文件都添加到版本控制中,这很可能不是您想要的。
Kaitain

473

git cherry-pick <original commit sha>
将复制原始提交,实质上重新应用提交

还原还原将执行相同的操作,并带有更复杂的提交消息:
git revert <commit sha of the revert>

这两种方式都将允许您git push不覆盖历史记录,因为它会在还原后创建一个新的提交。
输入commit sha时,通常只需要前5个或6个字符:
git cherry-pick 6bfabc


60
这很容易是OP问题的最优雅,最完整的解决方案。关于还原提交位于提交树的HEAD的假设要比接受的答案好得多。操作人员还特别要求提供一种不会重写历史记录的解决方案,因此,已接受的答案中提供的硬性解决方案完全是错误的。
Timo

6
@Timo为了明确起见,接受的答案包含我使用的解决方案(“还原还原”),并在我提出问题的几个小时内发布- 比该答案三年。因此,复选标记。
JimmidyJoo

6
@JimmidyJoo我知道我迟到了3年,我只是希望人们通过Google搜索来到这里,以找到更好的答案
Stephan

2
@Stephan Yep,不过,再次澄清一下,这是一个更好的答案,但不是我用来解决问题的答案。我只是在评论为什么复选标记在哪里。对所有人的问题:SO公约是否规定我应该“保留”过去的问题并在出现新答案时重新分配对勾标记?
JimmidyJoo

3
@JimmidyJoo我对SO约定一无所知。但是作为一个谷歌搜索者,我真的更喜欢看到更好的答案。并感谢任何人为保持自己过去的问题所做的努力。
Paiman Roointan

28

还原提交就像git中的任何其他提交一样。意思是,您可以还原它,如下所示:

git revert 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746

显然,只有在推送更改后才有意义,尤其是当您无法强制将其推送到目标分支时(这对于您的master分支是个好主意)。如果尚未推送更改,请按照其他帖子的说明进行选择,还原或仅删除还原提交。

在我们的团队中,我们有一条规则,对在主分支中提交的“还原”提交使用“ 还原 ”,主要是为了保持历史记录的清洁,以便您可以看到哪个提交还原了以下内容:

      7963f4b2a9d   Revert "Revert "OD-9033 parallel reporting configuration"
      "This reverts commit a0e5e86d3b66cf206ae98a9c989f649eeba7965f.
                    ...
     a0e5e86d3b6    Revert "OD-9055 paralel reporting configuration"
     This reverts commit 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746.
                ...
     Merge pull request parallel_reporting_dbs to master* commit 
    '648d7d808bc1bca6dbf72d93bf3da7c65a9bd746'

这样,您就可以追溯历史并弄清楚整个故事,即使那些不了解遗产的人也可以自己解决。而如果您随意挑选或重新编排内容,则这些有价值的信息将会丢失(除非您将其包括在注释中)。

显然,如果一次提交的还原和重新还原不止一次,则将变得非常混乱。


14

还原还原即可解决问题

例如,

如果abcdef是您的提交,并且ghijkl是还原提交时拥有的提交abcdef,请运行:

git revert ghijkl

这将还原还原


4

对我来说这看起来很愚蠢。但是我一直处在相同的情况下,并且确实为还原的提交还原了。我做了数字还原,所以我必须为每个“还原提交”进行还原。

现在我的提交历史看起来有点奇怪。

奇怪的历史

这是一个宠物项目,所以还可以。但是对于现实生活中的项目,我会优先选择最后一次提交,然后再还原,将所有已还原的代码一起还原到一个提交中,并添加更合理的注释。


4
:你可能有兴趣在回答我的另一个问题stackoverflow.com/questions/10415565/...
JimmidyJoo

2
您可以避免自动提交,并在还原时使用--no-commit标志选择提交消息,然后使用相关消息进行提交
David Barda

另外,在使用git revert时,您可以指定多个提交ID(它们必须按照我认为的正确顺序)。
Aalex Gabi

我可以从github桌面上执行此操作吗?
Guillaume F.

4

这是我的操作方法:
如果分支my_branchname包含在已还原的合并中。我想撤消my_branchname

我首先git checkout -b my_new_branchnamemy_branchname
然后在第一个提交之前(请参阅参考资料)进行一次提交的提交哈希(在git reset --soft $COMMIT_HASH哪里), 然后进行新提交, 然后上推新分支, 然后对新分支提出拉取请求。$COMMIT_HASHmy_branchnamegit log
git commit -m "Add back reverted changes"
git push origin new_branchname


当有太多的“樱桃选择”要做时,要走的路。我不明白为什么这个答案很少投票
Fundhor

2

或者,您可以git checkout -b <new-branch>git cherry-pick <commit>之前的并git rebase删除revert提交。像以前一样发送请求请求。


1

如果您不喜欢“还原还原”的想法(尤其是当这意味着丢失许多提交的历史记录信息时),则可以随时访问有关“还原错误的合并”的git文档。

鉴于以下开始情况

 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E   <-- fixed-up topic branch

(W是您对合并M的初始还原; D和E是对您最初损坏的功能分支/提交的修复)

现在,您可以简单地将提交A重新提交到E,这样它们都不“属于”还原的合并:

$ git checkout E
$ git rebase --no-ff P

现在可以master再次合并分支的新副本:

   A'---B'---C'------------D'---E'  <-- recreated topic branch
  /
 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E

好主意,感谢您的doc链接。我们通常在合并之前先用master重新设置,但是git然后似乎认识到A',B',C'与之前的相同,现在我在W(pastebin)之后有D,E 。有关如何解决此问题的建议?
克里斯托弗·巴克乔德

0

要取回在提交后已还原的未暂存和暂存的更改,请执行以下操作:

git reset HEAD@{1}

要恢复所有未暂存的删除:

git ls-files -d | xargs git checkout --
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.