Git:恢复连续但不是最近的多个提交

时间:2015-07-07 03:21:06

标签: git git-revert

我读了How I reverted several git commits in a single commit,这正是我想要的结果。但是,我确实希望在一次提交中恢复所有提交,因为1)有许多提交需要恢复2)我可能需要稍后恢复恢复。

我比链接中的示例更幸运,因为没有提交保留在要还原的那些中间。这就是我的历史:

A–C1–C2–C3–C4–O1–O2–O3

其中四个C提交是我想要恢复的,而O提交是由其他作者稍后提出的。

如何在一个提交R中恢复四个C,以后可以恢复它以使所有C再次生效?

1 个答案:

答案 0 :(得分:4)

与许多git命令git revert uses git rev-list (or the moral equivalent thereof) to parse its arguments一样:特别参见 OPTIONS 的说明。这意味着,除了其他方面,您可以简单地传递一系列提交,如the gitrevisions documentation中所述。请注意,C1..C4会排除C1本身 1 ,因此如果您使用此表单,请写下C1^..C4A0..C4

它负责指定要还原的提交,但仍然会留下一个可以进行四次新提交的恢复:

$ git revert 22b38d1^..676699a

没有做你想做的事。 2 你想要的也列在那些 OPTIONS 中,而且只是-n(或--no-commit ,同样的事情):

$ git revert -n 22b38d1^..676699a
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
You are currently reverting commit 22b38d1.
  (all conflicts fixed: run "git revert --continue")
  (use "git revert --abort" to cancel the revert operation)
[remainder snipped]

现在所有四个提交都已恢复,但是没有提交,所以现在我必须手动提交结果。如果我运行git revert --continue git将为我提交,但只提及第一次还原(22b38d1,在这种情况下 - 反转是以相反方式完成的,{ {1}}先完成,以防需要恢复之前的提交,依此类推。)

676699a

这会给编辑器带来一个“恢复(第一次提交)”消息,我现在可以解决这个问题:“一次性恢复22b38d1 ^ .. 676699a”。 (构建一个好的reversion消息可能很困难; git默认为自动提交就足够了,但在这种情况下默认为$ git commit ,不是。)

Git是git,当然,你可以使用相同的技术,不用 -n 你链接的帖子中提到的-n :将四个恢复器压缩成一个单独的恢复,但使用壁球动作来组合提交文本。在这里你可以运行:

git rebase -i

你可能更喜欢这第二种方法(我想我自己更喜欢它,它不是你要求的那样)。

关于此问题的附注:$ git revert --no-edit 22b38d1^..676699a [messages omitted] $ git rebase -i HEAD~4 [editor runs: change last three to "squash", write, exit editor] [editor runs again: edit commit message to describe 4-in-1 reversion] 使用临时匿名分支,只需副本(就好像通过挑选)提交。要使用您的符号,请从以下开始:

git rebase

并在四次恢复之后获取(没有A – C1 – C2 – C3 – C4 – O1 – O2 – O3 <-- branch ,进行四次新提交),这个:

-n

其中R是C的逆转。然后,rebase复制原始的R,在rebase启动时加上副本(在这种情况下,最终只是一个我称之为 R4 - R3 - R2 - R1 <-- branch / A – C1 – C2 – C3 – C4 – O1 – O2 – O3 的提交),并移动分支标签所以它指向最后一个新提交(使临时分支再次成为永久性):

R

R4 - R3 - R2 - R1 [abandoned] / A – C1 – C2 – C3 – C4 – O1 – O2 – O3 - R <-- branch R1会发生什么?他们已经被遗弃,并最终被 3 垃圾收集。

1 除非您使用R4,否则会在--boundary输出中标记边界提交-。我没有使用git rev-list对此进行测试:在图表中移回一个提交的帽子后缀就足够了,这是我通常用于这些情况的内容。 (如果你达到root提交,它就会失败,但这不会发生在这里。)

2 不仅因为那些特定的提交哈希值对于我运行这些命令的存储库来说也是唯一的。你的哈希会有所不同;或者您可以使用git revert或等效HEAD~6^..HEAD~3等相对名称。这假设你提交图片段的绘制是准确的,从那以后你没有做任何事情来移动HEAD~7..HEAD~3

3 旧的提交仍然可以通过HEAD和您的分支的reflog找到。默认情况下,这会将它们保留30天,之后旧的reflog条目将过期并被删除,然后 a HEAD(包括任何自动git根据需要执行的操作)将删除这些提交。