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

Rob*_*obM 40 git merge git-rebase

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

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

我已经读过其他问题,git log --merge如果我使用的话会显示父提交git merge.当我遇到冲突并被告知时,我还是尝试过fatal: --merge without MERGE_HEAD?.

如何识别有问题的提交?

Ale*_*own 39

简答

如果它说

Patch failed at 0001 commit message for F
Run Code Online (Sandbox Code Playgroud)

然后跑

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
Run Code Online (Sandbox Code Playgroud)

获取ad1c77失败提交的SHA ,然后使用它git show ad1c77来查看它.

答案很长

让我们从这棵树开始:

A---B---C---D
     \
      E---F---G

$ git checkout G
$ git rebase D
Run Code Online (Sandbox Code Playgroud)

当发生rebase冲突时,它之间会发生冲突

  • 上游的变化(C--D从共同的祖先() B)PLUS已经重订的变化和已经解决冲突(E')
  • 下一个commit(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'
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

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
Run Code Online (Sandbox Code Playgroud)

首先,您可以看到它F,因为提交消息出现.但是,如果您的提交消息都看起来像"foo","documentation"或"some fixes",那么这将无济于事,您确实需要SHA ID ad1c77或补丁内容.

以下是如何找出真实身份F:

当它列出rebase冲突时,它会说:

Patch failed at 0001 commit message for F
Run Code Online (Sandbox Code Playgroud)

现在看看.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
Run Code Online (Sandbox Code Playgroud)

补丁文件包含原始commit-id

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
Run Code Online (Sandbox Code Playgroud)

然后你可以看一下.

必须有一个更简单的方法,但这是有效的.

请注意,修补程序失败的事实可能是由于不同的提交(如果您要重新定位到共同的祖先HEAD和rebase目标).发现提交相当复杂,尽管你可以尝试反向修改它来找到它:

$ git checkout D
$ git rebase G
Run Code Online (Sandbox Code Playgroud)


jav*_*ett 10

git rebase停止解决冲突的过程中,以下命令将显示冲突的提交(所有这些,而不仅仅是冲突的文件),即,您的提交当前正在重播​​/重新定位到新基础上,无论您在哪里 -至:

git show $(< .git/rebase-apply/original-commit)
Run Code Online (Sandbox Code Playgroud)

如果您只想查看特定冲突文件(您正在解析的文件)的冲突,请隔离:

git show $(< .git/rebase-apply/original-commit) -- /path/to/conflicting/file
Run Code Online (Sandbox Code Playgroud)

没有猫在这个答案的构建中被滥用:).


red*_*bmk 9

显示当前/失败的提交

这可能是一个新功能,但REBASE_HEAD会为您提供当前停止的提交(例如,如果提交未能应用)。如果您想完整查看提交,可以使用

git show REBASE_HEAD
Run Code Online (Sandbox Code Playgroud)

作为更详细的替代方法,您可以使用git rebase --show-commit-patch. 文档说它们是等效的。

显示自您开始工作以来发生的变化

如果您想查看重新定位的位置和重新定位的位置之间发生了什么变化,您可以获取两个分支之间的差异。例如,如果你从基础重建masterorigin/master你可以使用:

git diff master..origin/master
Run Code Online (Sandbox Code Playgroud)

或者,如果您想将更改视为单独的提交:

git log -p master..origin/master
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢使用散列,或者可能在一段时间后回到变基并且不记得要变基的分支,您可以使用git status查看两个分支。例如:

您目前正在将分支 'master' 重新设置为 'b5284275'

然后,要查看发生了什么变化,您可以使用:

git diff master..b5284275
Run Code Online (Sandbox Code Playgroud)


Von*_*onC 6

从 Git 2.17(2018 年 3 月)开始,您不需要使用rebase-apply.

新的“ --show-current-patch”选项提供了一种面向最终用户的方式,可以diff在“ git rebase”(和“ git am”)因冲突而停止时应用。

请参阅Nguy?n Thái Ng?c Duy ( ) 的commit fbd7a23commit 6633529commit 984913a(2018 年 2 月 11 日(由Junio C Hamano合并-- --提交 9ca488c 中,2018 年 3 月 6 日)pclouds
gitster

am: 添加 --show-current-patch

签字人:Nguy?n Thái Ng?c Duy

指向用户$GIT_DIR/rebase-apply可能会鼓励他们在那里乱搞,这不是一件好事。

这样,当用户需要查看补丁时,用户不必将路径保留在某处(因为在执行几个命令后,路径可能会超出回滚缓冲区)。

在“显示当前的 git 交互式 rebase 操作”中查看更多信息

例子:

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".
Run Code Online (Sandbox Code Playgroud)

然后你会得到:

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
Run Code Online (Sandbox Code Playgroud)

git am --short-current-patch”是显示停止步骤的邮件的一种方式,不适合直接输入“ git apply”(它被设计为一个很好的“ git am”输入)。

在 Git 2.26(2020 年第一季度)中,它学习了一个仅显示补丁部分的新选项。

请参阅Paolo Bonzini ( ) 的commit aa416b2commit f3b4822commit e8ef1e8commit bc8620bcommit 62e7a6f(2020 年 2 月 20 日(由Junio C Hamano合并-- --0e0d717 提交中,2020 年 3 月 9 日)bonzini
gitster

am: 支持 --show-current-patch=diff 检索 .git/rebase-apply/patch

报告人:J. Bruce Fields
签字人:Paolo Bonzini

git am --show-current-patch提交 984913a210中添加“ ” (“ am:add --show-current-patch”,2018 年 2 月 12 日,Git v2.17.0-rc0 --合并第 7 批中列出)时,“ git am”开始推荐它作为的替代品.git/rebase-merge/patch

不幸的是,这个建议有些误导;例如,如果“ git am --show-current-patch”的输出git apply被编码为quoted-printable 或base64,则不能将其传递给“ ”。

为“ git am --show-current-patch”添加一个新模式以纠正建议。

新的模式diff

--show-current-patch[=(diff|raw)]

显示git am因冲突而停止的消息。
如果raw指定,则显示电子邮件消息的原始内容;如果diff,仅显示差异部分。
默认为raw.

和:

am: support--show-current-patch=raw作为同义词--show-current-patch

签字人:Paolo Bonzini

为了简化工作树操作并避免用户进入.git,如果“ git am”还提供一种复制.git/rebase-merge/patch到标准输出的模式会更好。

一种可能性是拥有完全独立的选项,例如引入--show-current-message(for .git/rebase-apply/NNNN) 和--show-current-diff(for .git/rebase-apply/patch),同时可能弃用 --show-current-patch。

这甚至可以消除对系列中前两个补丁的需求。但是,较长的公共前缀会阻止使用诸如“ --show”之类的缩写选项。

因此,我选择将字符串参数添加到--show-current-patch.