恢复合并时如何找出分支号?
Posted
技术标签:
【中文标题】恢复合并时如何找出分支号?【英文标题】:How to find out branch numbers when reverting a merge? 【发布时间】:2014-02-13 05:36:25 【问题描述】:我的提交历史如下:
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
继续恢复链。
问题是:我怎么知道哪个数字代表哪个分支?
【问题讨论】:
你为什么不直接git checkout A
?如果需要切换分支指向 A,git checkout A; git branch -D NAME; git branch NAME; git checkout NAME
。您仍然可以结帐任何 ABCDEX 或 Y。
实际上我正在使用远程仓库,在这种情况下,我只能恢复,不能重置和结帐。
我会在 A 和 HEAD 之间生成一个补丁,然后使用 patch -R
反向应用它。
啊。所以你想要一个新的提交来“回到过去”,对吧?
@Kaz 正是我要提出的建议!
【参考方案1】:
您可以检查合并提交以查看其父级:
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&P 代码,如果X
和Y
发生很大变化,或者如果您执着于保持最准确的历史记录,这是一个有吸引力的选择可能(我倾向于那样)。
要重新引入X
和Y
,您应该这样做:
git revert D'
这可能会产生合并冲突,尤其是如果您不同时还原 B'
和 C'
,但这可能比手动重新执行 X
和 Y
更好。 Linux Torvalds 写了a very thorough explanation of this scenario 可能对你有一些帮助。
【讨论】:
启动一个新分支不会将那个分支恢复到A点。每个人都必须切换到新分支。他可能也不想重置,因为这是一个非快进更改。 啊。他没有在他的问题中指定任何关于公共回购的信息,这很关键。 他确实指定重置为 A 是不可接受的。如果这些更改未发布到任何其他存储库,则该解决方案没有理由不可接受。【参考方案2】:另一种方法是简单地清空工作树,然后插入工作树-as-it-was-at-commit-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
中相同的树和文件。
【讨论】:
【参考方案3】:在这种情况下,我不会在 git 上绞尽脑汁,而是这样做:
git diff <sha(A)> HEAD | git apply -R
git commit -a -m "undoing everything since A"
当然,在提交之前检查所有内容。另外,在提交之后,验证:现在 A 和 HEAD 有什么区别?理想情况下,什么都没有:
git diff <sha(A)> HEAD
【讨论】:
@Andy Envy;复仇;在智能手机的小屏幕上笨拙地涂抹; TCP/IP 校验不足... :) @Kaz 我只是想给你投票,但我没有足够的声誉:( 还有另一种方法可以避免需要 diff-and-apply,因此稍微容易一些(有时但并不总是更快);我会添加它作为答案。以上是关于恢复合并时如何找出分支号?的主要内容,如果未能解决你的问题,请参考以下文章