当我使用git rebase
遇到合并冲突时,如何根据提交确定冲突来源,而不仅仅是文件差异?
我已经知道如何在git mergetool
之前(基本)使用git add
或git rebase --continue
,但有时文件之间的差异还不够:我想查看提交刚刚未能应用于工作树的提交的日志和差异。
如果我使用git log --merge
,我会在其他问题中读到git merge
会显示父提交。当我遇到冲突并且被告知fatal: --merge without MERGE_HEAD?
时,我尝试了它。
如何识别有问题的提交?
答案 0 :(得分:39)
如果说
Patch failed at 0001 commit message for F
然后运行
$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
获取失败提交的SHA ad1c77
,然后使用git show ad1c77
查看它。
让我们从这棵树开始:
A---B---C---D
\
E---F---G
$ git checkout G
$ git rebase D
发生rebase冲突时,
之间存在冲突C--D
)来自共同祖先(B
) PLUS 已经重新定义的更改和已解决的冲突(E'
)与 F
)让我们看看会发生什么:
1) A---B---C---D---E' <- E patched and committed successfully as E'
2) A---B---C---D---E'--- <- failed to patch F onto E'
以下是错误消息:
First, rewinding head to replay your work on top of it...
Applying: commit message for F
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging 1.txt
CONFLICT (content): Merge conflict in 1.txt
Failed to merge in the changes.
Patch failed at 0001 commit message for F
首先,您可以看到它是F
,因为会出现提交消息。但是,如果您的提交消息都看起来像“foo”,“documentation”或“some fixes”,那么这将无济于事,而您确实需要SHA id ad1c77
或补丁内容。
F
:当它列出rebase冲突时,它会说:
Patch failed at 0001 commit message for F
现在查看.git/rebase-apply/
,您将在其中找到补丁文件0001
:
$ ls .git/rebase-apply
0001 head-name msg orig-head sign
0002 info msg-clean patch threeway
apply-opt keep next quiet utf8
final-commit last onto rebasing
补丁文件包含原始commit-id
$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
然后你可以看一下。
必须有一种更简单的方法,但这有效。
请注意,补丁失败的事实可能是由于不同的提交(如果您正在重新定位到HEAD
的共同祖先和rebase目标)。发现提交相当复杂,尽管您可以尝试反向执行rebase来找到它:
$ git checkout D
$ git rebase G
答案 1 :(得分:9)
在停止解决冲突的git rebase
期间,以下命令将显示冲突的提交(所有这些,而不仅仅是冲突的文件),即您当前正在重播/重新绑定到新基础的提交,无论你在哪里:
git show $(< .git/rebase-apply/original-commit)
如果您只想查看特定冲突文件(您要解析的文件)的冲突,请隔离:
git show $(< .git/rebase-apply/original-commit) -- /path/to/conflicting/file
没有猫在构建这个答案时被滥用:)。
答案 2 :(得分:3)
这可能是一项新功能,但是REBASE_HEAD
为您提供了您当前停止的提交(例如,提交失败的情况)。如果您想查看全部提交,可以使用
git show REBASE_HEAD
作为更详细的选择,您可以使用git rebase --show-commit-patch
。文档说它们是等效的。
如果您想查看在您的基础所在位置与您的基础之间更改了什么,可以在两个分支之间找到区别。例如,如果您要从master
迁移到origin/master
,则可以使用:
git diff master..origin/master
或者如果您希望将更改作为单独的提交查看:
git log -p master..origin/master
如果您更喜欢使用哈希,或者过了一会儿又回到了基准站,并且不记得要重新建立哪个分支,则可以使用git status
查看这两个分支。例如:
您当前正在将'b5284275'的分支'master'重新设基
然后,要查看更改,可以使用:
git diff master..b5284275
答案 3 :(得分:2)
cat .git/rebase-apply/original-commit
鉴于此:
A---B---C---D
\
E---F---G
$ git checkout G
$ git rebase D
并且考虑到尝试应用F的合并冲突:
A---B---C---D--E'--!
\
E---F---G
然后original-commit
文件将显示F的散列。这是“他们的”版本。
此外,在这种情况下,HEAD(.git / HEAD)将为E'。这是“我的”版本。 HEAD ^将是“基础”版本。
至少git 1.7.9
答案 4 :(得分:1)
我不知道为什么我的情况没有.git/rebase-apply
。对于处于相同情况的人,这是我的变体。
git show $(cat .git/rebase-merge/stopped-sha)
或者作为别名...
git config --global alias.sp='!git show $(cat .git/rebase-merge/stopped-sha)'
答案 5 :(得分:1)
自Git 2.17(2018年3月)以来,您不需要使用rebase-apply
。
新的“ --show-current-patch
”选项提供了一种面向最终用户的方式,可在“ diff
”(和“ git rebase
”)停止时使用git am
冲突。
请参见commit fbd7a23的commit 6633529,commit 984913a,Nguyễn Thái Ngọc Duy (pclouds
)(2018年2月11日)。
(由Junio C Hamano -- gitster
--在commit 9ca488c中合并,2018年3月6日)
am
:添加--show-current-patch签名人:NguyễnTháiNgọcDuy
将用户指向
$GIT_DIR/rebase-apply
可能会鼓励他们到那里乱逛,这不是一件好事。有了这个,用户在需要查看补丁时不必将路径保持在某个地方(因为在执行了几个命令之后,该路径可能不在回滚缓冲区内)。
在“ Show current git interactive rebase operation”中查看更多信息
示例:
C:\Users\VonC\repo\src>git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: change code
Using index info to reconstruct a base tree...
M a/src/file
Falling back to patching base and 3-way merge...
Auto-merging a/src/file
CONFLICT (content): Merge conflict in a/src/file
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch' to see the failed patch <======
Patch failed at 0001 change code
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
您将得到:
C:\Users\VonC\rep\src>git am --show-current-patch
commit xxx (master)
Author: VonC <vonc@vonc.com>
Date: Mon Nov 4 13:59:18 2019 +0100
change code
diff --git a/a/src/file b/a/src/file
index yyy..zzz 100644
--- a/a/src/file
+++ b/a/src/file
@@ -13,5 +13,5 @@ file: /a/src
content line 1
content line 2
content line 3
content line 4
-content line 5
-content line 6
+content bis line 5
+content bis line 6
答案 6 :(得分:0)
很多时候,你会陷入困境,并希望跳过那些不需要的提交。
很遗憾,虽然git status
告诉您,您处于提交过程中并建议使用git rebase --continue
git rebase --skip
或git rebase --abort
,但它并不是告诉你你目前的承诺。
因此,通常很难知道您是否应该git rebase --skip
。
但是,仍有一种方法可以通过运行来找出您所执行的提交:
git log -1 $(< .git/rebase-apply/original-commit)
答案 7 :(得分:0)
要查看发生冲突时正在应用的提交,请使用...
git am --show-current-patch