Git:恢复连续但不是最近的多个提交
Git: Reverting multiple commits that are contiguous but not most recent
我读了 How I reverted several git commits in a single commit,这正是我想要的结果。但是,我确实想在一次提交中还原所有内容,因为 1) 有很多提交要还原 2) 很可能我需要稍后还原这些还原。
我比 link 中的示例幸运,因为在要还原的提交中间没有要保留的提交。这就是我的历史:
A–C1–C2–C3–C4–O1–O2–O3
其中四个 C 提交是我要还原的,O 提交是其他作者后来做出的。
如何在一个提交 R 中还原四个 C,稍后可以还原以使所有 C 再次生效?
像许多 git 命令一样,git revert
uses git rev-list
(or the moral equivalent thereof) to parse its arguments: see in particular the description of OPTIONS. This means, among other things, that you can simply pass a range of commits, as spelled out in the gitrevisions
documentation。请记住,C1..C4
排除了 C1
本身 1,因此如果您使用这种形式,请写 C1^..C4
或 A0..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 会为我做一个提交,但只会提到 first 回退(22b38d1
,在这个case——恢复是反向完成的,676699a
首先完成,以防需要恢复之前的提交,依此类推。
$ git commit
这会向编辑器显示 "reverts (the first commit)" 消息,我现在可以将其修改为 "revert 22b38d1^..676699a in one swoop"。 (构造一个好的恢复消息可能很困难;git 的默认自动提交就足够了,但在这种情况下,-n
的默认值就不够了。)
Git 是 git,当然,您可以使用相同的技术 without the -n
and with 您链接的帖子中提到的 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
使用临时的匿名 b运行ch 简单地 复制 (就像通过挑选樱桃一样)提交。要使用您的符号,您从:
开始
A – C1 – C2 – C3 – C4 – O1 – O2 – O3 <-- branch
并获取,在四次恢复之后(没有 -n
,进行四次新提交),这个:
R4 - R3 - R2 - R1 <-- branch
/
A – C1 – C2 – C3 – C4 – O1 – O2 – O3
其中 R 是 C 的反转。然后,rebase 复制原始 R,在 rebase 开始时添加副本(在这种情况下,最终只是一个提交,我将其称为 R
),并移动 b运行ch 标签,以便它指向最后一个新提交(使临时 b运行ch 再次永久化):
R4 - R3 - R2 - R1 [abandoned]
/
A – C1 – C2 – C3 – C4 – O1 – O2 – O3 - R <-- branch
R1
到 R4
会怎样?它们已被遗弃,最终被3 垃圾收集。
1除非你使用 --boundary
,但在 git rev-list
输出中用 -
标记边界提交。我没有用 git revert
测试过这个:帽子后缀在图中移回一次提交就足够了,这也是我通常在这些情况下使用的。 (如果您到达根提交,它会失败,但这不会发生在这里。)
2不仅仅是因为那些特定的提交哈希对于我 运行 这些命令所在的存储库是唯一的。您的哈希值会有所不同;或者您可以使用相对名称,例如 HEAD~6^..HEAD~3
或等效的 HEAD~7..HEAD~3
。这假设您绘制的提交图片段是准确的,并且从那时起您没有做任何移动 HEAD
.
3仍然可以通过 HEAD
和您的 b运行ch 的引用日志找到旧的提交。默认情况下,这会使它们保留 30 天,之后旧的 reflog 条目将过期并被删除,然后 then a git gc
(包括任何自动的 git需要)将删除这些提交。
我读了 How I reverted several git commits in a single commit,这正是我想要的结果。但是,我确实想在一次提交中还原所有内容,因为 1) 有很多提交要还原 2) 很可能我需要稍后还原这些还原。
我比 link 中的示例幸运,因为在要还原的提交中间没有要保留的提交。这就是我的历史:
A–C1–C2–C3–C4–O1–O2–O3
其中四个 C 提交是我要还原的,O 提交是其他作者后来做出的。
如何在一个提交 R 中还原四个 C,稍后可以还原以使所有 C 再次生效?
像许多 git 命令一样,git revert
uses git rev-list
(or the moral equivalent thereof) to parse its arguments: see in particular the description of OPTIONS. This means, among other things, that you can simply pass a range of commits, as spelled out in the gitrevisions
documentation。请记住,C1..C4
排除了 C1
本身 1,因此如果您使用这种形式,请写 C1^..C4
或 A0..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 会为我做一个提交,但只会提到 first 回退(22b38d1
,在这个case——恢复是反向完成的,676699a
首先完成,以防需要恢复之前的提交,依此类推。
$ git commit
这会向编辑器显示 "reverts (the first commit)" 消息,我现在可以将其修改为 "revert 22b38d1^..676699a in one swoop"。 (构造一个好的恢复消息可能很困难;git 的默认自动提交就足够了,但在这种情况下,-n
的默认值就不够了。)
Git 是 git,当然,您可以使用相同的技术 without the -n
and with 您链接的帖子中提到的 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
使用临时的匿名 b运行ch 简单地 复制 (就像通过挑选樱桃一样)提交。要使用您的符号,您从:
A – C1 – C2 – C3 – C4 – O1 – O2 – O3 <-- branch
并获取,在四次恢复之后(没有 -n
,进行四次新提交),这个:
R4 - R3 - R2 - R1 <-- branch
/
A – C1 – C2 – C3 – C4 – O1 – O2 – O3
其中 R 是 C 的反转。然后,rebase 复制原始 R,在 rebase 开始时添加副本(在这种情况下,最终只是一个提交,我将其称为 R
),并移动 b运行ch 标签,以便它指向最后一个新提交(使临时 b运行ch 再次永久化):
R4 - R3 - R2 - R1 [abandoned]
/
A – C1 – C2 – C3 – C4 – O1 – O2 – O3 - R <-- branch
R1
到 R4
会怎样?它们已被遗弃,最终被3 垃圾收集。
1除非你使用 --boundary
,但在 git rev-list
输出中用 -
标记边界提交。我没有用 git revert
测试过这个:帽子后缀在图中移回一次提交就足够了,这也是我通常在这些情况下使用的。 (如果您到达根提交,它会失败,但这不会发生在这里。)
2不仅仅是因为那些特定的提交哈希对于我 运行 这些命令所在的存储库是唯一的。您的哈希值会有所不同;或者您可以使用相对名称,例如 HEAD~6^..HEAD~3
或等效的 HEAD~7..HEAD~3
。这假设您绘制的提交图片段是准确的,并且从那时起您没有做任何移动 HEAD
.
3仍然可以通过 HEAD
和您的 b运行ch 的引用日志找到旧的提交。默认情况下,这会使它们保留 30 天,之后旧的 reflog 条目将过期并被删除,然后 then a git gc
(包括任何自动的 git需要)将删除这些提交。