如何在git rebase期间通过哈希识别冲突提交?

时间:2010-01-22 15:40:39

标签: git merge git-rebase

当我使用git rebase遇到合并冲突时,如何根据提交确定冲突来源,而不仅仅是文件差异?

我已经知道如何在git mergetool之前(基本)使用git addgit rebase --continue,但有时文件之间的差异还不够:我想查看提交刚刚未能应用于工作树的提交的日志和差异。

如果我使用git log --merge,我会在其他问题中读到git merge会显示父提交。当我遇到冲突并且被告知fatal: --merge without MERGE_HEAD?时,我尝试了它。

如何识别有问题的提交?

8 个答案:

答案 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 fbd7a23commit 6633529commit 984913aNguyễ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 --skipgit rebase --abort,但它并不是告诉你你目前的承诺。

因此,通常很难知道您是否应该git rebase --skip

但是,仍有一种方法可以通过运行来找出您所执行的提交:

git log -1 $(< .git/rebase-apply/original-commit)

答案 7 :(得分:0)

要查看发生冲突时正在应用的提交,请使用...

git am --show-current-patch