我的提交历史如下:
A - B - C - D - E
\ /
X - Y
分支ABCDE
是master
,分支XY
是其他分支(比如test
),D
是合并提交。 HEAD
现在位于E
。假设不使用A
,我需要将我的工作目录返回到git reset --hard <SHA1(A)>
状态,仅git revert
。据我所知,在这种情况下,这可以通过两种方式完成:
第一种方式:
git revert --no-commit <SHA1(E)>
git revert -m 1 --no-commit <SHA1(D)>
git revert --no-commit <SHA1(C)>
git revert --no-commit <SHA1(B)>
git commit -m "Reverted to state A"
第二种方式:
git revert --no-commit <SHA1(E)>
git revert -m 2 --no-commit <SHA1(D)>
git revert --no-commit <SHA1(Y)>
git revert --no-commit <SHA1(X)>
git revert --no-commit <SHA1(B)>
git commit -m "Reverted to state A"
绊脚石是git revert -m
。在此示例中,我假设1
允许沿分支master
和2
- 沿分支test
继续恢复链。
问题是:我如何知道哪个数字意味着哪个分支?
答案 0 :(得分:2)
另一种方法是简单地清空工作树,然后插入工作树 - 因为它在提交 - A
:
# assumes you're in the top level
$ git rm -rf .
$ git checkout sha-or-other-specifier-for-A -- .
$ git commit -m 'revert to state A'
这里的想法是git rm -rf
完全清空工作树和索引/登台区域,然后git checkout <rev> -- .
完全重新填充工作树和索引/暂存,但获取来自指定修订版本的树和文件,而不是来自最新版本。
完成这两项后,新提交将写入与提交A
中相同的树和文件。
答案 1 :(得分:1)
在这种情况下,我不会把我的大脑放在git上,只是这样做:
git diff <sha(A)> HEAD | git apply -R
git commit -a -m "undoing everything since A"
当然,在提交之前检查所有内容。此外,在提交之后,验证:A和HEAD之间有什么区别?理想情况下,没有:
git diff <sha(A)> HEAD
答案 2 :(得分:0)
您可以检查合并提交以查看其父母是谁:
git show <SHA1(D)>
父母将按照您可以参考的顺序列出。此信息也会打印在git log
的输出中。使用它来推断在执行git revert -m
时意味着哪些提交。
编辑:您似乎正在使用公共存储库并寻找更改已发布分支的方法,这与更改工作副本的状态完全不同。 Git有一种方法可以恢复,而不必在整个过程中找出合并的每个父级。一下子就这么做:
git revert <SHA1(B)>..
更新:我正在仔细阅读一些旧内容,并意识到我给出的答案完全不正确。如果你这样做,你就不会得到州A,但你会得到一个你不想要的弗兰肯斯坦:
A - C' - D' - E'
\ /
X - Y
那^相当于你得到的东西,这根本不是你想要的。实际上只有一种方法可以完全保留您的历史记录:
git revert HEAD # reverts E, labeled as E' below
git revert -m 1 <SHA1(D)> # reverts D, labeled as D' below
git revert HEAD # reverts C, labeled as C' below
git revert HEAD # reverts B, labeled as B' below
这会让你的历史看起来像这样:
A - B - C - D - E - E' - D'{C} - C' - B'
\ /
X - Y
此方法可以满足您的需求并保留历史记录。 @Kaz和@ torek的方法更有效,更简洁,如果你不关心重新引入X
和Y
,那么我推荐其中一种解决方案;但是,如果您关心的话,它们会使X
和Y
重新引入您的主分支更加困难。还原每个部分可以重新引入X
和Y
而无需重新编写/再次使用C&amp; P代码,如果X
和Y
发生较大变化,这是一个很有吸引力的选择如果你对保持最准确的历史记录感到痴迷(我倾向于这样)。
要重新引入X
和Y
,您应该这样做:
git revert D'
这可能会产生合并冲突,特别是如果您还没有还原B'
和C'
,但这可能比重新执行X
和Y
更好用手。 Linux Torvalds写了a very thorough explanation of this scenario,可能对你有所帮助。