还原git中的一系列提交


127

如何在git中还原一系列提交?通过查看gitrevisions文档,我看不到如何指定所需的范围。例如:

A -> B -> C -> D -> E -> HEAD

我想做相当于:

git revert B-D

结果将是:

A -> B -> C -> D -> E -> F -> HEAD

其中F包含BD的反数(含BD)。


在gitrevisions(7)页面的末尾,有一个标题为“ SPECIFYING RANGES”的部分。您想要什么与那里描述的有什么不同?
Gareth McCaughan

2
gitrevisions页面建议'git revert A..​​D'将执行我想要的操作。但是,当我尝试出现错误“致命:找不到A..D”时
Alex Spurling

Answers:


172

您正在使用哪个版本的Git?

仅在Git1.7.2 +中支持还原多个提交:有关更多详细信息,请参见“ 使用还原多次回滚到旧提交。 ”。
当前的git revert手册页仅适用于当前的 Git版本(1.7.4+)。


正如OP Alex Spurling在评论中所述:

升级到1.7.4可以正常工作。
为了回答我自己的问题,这是我想要的语法:

git revert B^..D 

B^表示“ B的第一个父提交”:允许包含B在还原中。
请参阅“ git rev-parse规范修订版”部分,其中包括<rev>^,例如HEAD^语法:请参见“ 插入号(^)字符是什么意思? ”中的更多内容。)

请注意,每个还原的提交都是单独提交的。

Henrik N评论中澄清:

git revert OLDER_COMMIT^..NEWER_COMMIT

如下所示,您无需立即提交即可还原:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"

1
谢谢,这就是答案。升级到1.7.4可以正常工作。为了回答我自己的问题,这是我想要的语法:git revert B ^ .. D
Alex Spurling

天才。谢谢。对我而言,这还没有发生,我需要以相反的顺序还原提交才能应用补丁,apply。此命令说明了方式。
蒂姆·阿贝尔

5
我经常参考这个答案,而且我总是花点时间弄清楚顺序。因此,对我的未来自我有帮助:git revert OLDER_COMMIT^..NEWER_COMMIT
Henrik N

2
^是什么意思?
达斯汀·盖茨

1
@DustinGetz第一个父级:请参见git-scm.com/docs/gitrevisions:“ ^修订版参数的后缀表示该提交对象的第一个父级”。
VonC

15

如果您想在一次提交中将提交范围B还原为D(至少在git版本2中),则可以执行

 git revert -n B^..D

这会将提交所做的更改从B的父提交(排除)还原到D提交(包括),但不会使用还原后的更改创建任何提交。还原仅修改工作树和索引。

之后不要忘记提交更改

 git commit -m "revert commit range B to D"

您也可以使用相同的方法在单个提交中还原多个不相关的提交。例如还原B和D但不还原C

 git revert -n B D
 git commit -m "Revert commits B and D"

参考:https : //www.kernel.org/pub/software/scm/git/docs/git-revert.html

感谢Honza Haering更正


3
git revert -n B..D不还原提交B,仅git revert -n B^..D还原C和D。也 还原B。
Honza Haering

根据git文档。在帖子中引用
Ramast

1
如果您在引用:中引用此示例(我认为这有点令人困惑)git revert -n master~5..master~2,则表示包含了第五次最新提交。但master~5实际上是第六次最新提交。有关符号的详细信息,请参见git docs中的版本选择..:-)
Honza Haering

6

这样git revert OLDER_COMMIT^..NEWER_COMMIT做对我没有用。

我用过git revert -n OLDER_COMMIT^..NEWER_COMMIT,一切都很好。我正在使用git version 1.7.9.6


我遇到了同样的问题,并使用-n进行了修复,但是您应该将^保留为OLDER_COMMIT(git revert -n OLDER_COMMIT ^ .. NEWER_COMMIT)。
FeelGood 2012年

@FeelGood为什么你应该离开^?
奥兰多

我的历史记录为A-> B-> C,目标是还原B和C。当我运行'git revert -n B..C'时,仅还原了C。当我使用'git revert -n B ^ .. C'时,git恢复了两个提交。也许我做错了。
FeelGood 2012年

很酷,必须测试一下,但我认为在我的情况下效果很好(除非我还原了1个提交范围大声笑),我将修改答案以包括^。谢谢
奥兰多

2
-n--no-commit选项会恢复在一个单一的所有跨范围的变化犯,而不是创建一个还原承诺在范围内的所有承诺。最终结果相同,因为相同的更改将被还原。只取决于您希望git历史如何。
丹尼斯

0

用于git rebase -i将相关的提交压缩为一个。然后,您只需提交一次即可还原。


7
如果使用git rebase,则可以简单地删除提交。我认为有一个不重新设置基准的原因,例如想要保持提交F的SHA1不变。
圣保罗Ebermann

5
或者,将还原提交压缩为一个。
aeosynth
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.