Git帮助您了解基于合并的冲突

时间:2018-08-06 18:46:37

标签: git merge git-merge

我在未修改的文件上出现冲突。合并时,文件冲突只有一行更改。我开始了解可能发生的情况,但仍然无法解决问题。

这是分支结构。

    • current_iteration
      • mapr_autoinit

Master很老,很长一段时间以来都没有从current_iteration进行更改。但是,master通过直接将其他基础重新部署到master上,直接应用了更改。因此从技术上讲master和current_iteration有所不同。我们一直分支并标记current_iteration。我看到的问题是当我从current_iteration合并回分支时。我得到的冲突比基于current_iteration的更改所发生的冲突要多。我能够从current_iteration进行git diff / git的应用,并且干净地应用。

当我在mapr-autoinit上运行git show-branch --merge-base时,我看到该提交实际上是几个月前在master上的提交。但是,当我检查git merge-base current_iteration mapr_autoninit时,发现该版本是最新版本,很可能不会发生冲突。

从最近几天所看到的情况来看,如果我将master合并到current_iteration中,则提交,然后再将current_iteration合并回master中,这似乎是合乎逻辑的。这可能应该解决我的分支合并基础以指向更新的版本。

我也有可能停止跟踪主人。我尝试使用git config --unset branch.master.merge; git config --unset branch.master.remote停止跟踪母版,但这无法解决我的问题。

这是一个问题,即master和current_iteration分歧了,而合并正试图通过重播整个日志来调和合并吗?

这里还有更多细节。现在,我要提出一个新问题,因为该问题更加具体。我将根据有效的答案来更新这两个答案,或删除旧的答案(具体取决于哪个)。

Git merge resulting in unreasonable conflicts

1 个答案:

答案 0 :(得分:13)

我从没发现git show-branch输出对自己很有用,我不确定如何使用它,也不确定其他人如何成功使用它。

  

我也有可能停止跟踪主人...

这无关紧要。重要的是实际的提交图。任何分支的上游都独立于提交图。

  

这是一个问题,即master和current_iteration分歧了,而合并正试图通过重播整个日志来调和合并吗?

不。在 之后,merge-base-finding的重要之处仅在于,即合并基础提交,即加上两个分支提示提交。介于两者之间的所有内容都不相关。

  

但是,当我检查git merge-base current_iteration mapr_autoinit时,发现该版本是最新版本,很可能不会发生冲突。

这通常是入门的方法,因为git merge-base检查提交图,并使用它来计算合并基础提交。请注意,默认情况下,git merge运行的是git merge-base --all的等效项。如果这产生了个以上合并基础(多个提交哈希ID),则您有特殊情况。假设您暂时不这样做,但是检查是个好主意。

已经发现合并基础提交,您可以查看git log的输出(请参阅最后一节),并查看合并基础与两个分支技巧的关系。 Git对此并不在意-嗯,那不是很正确:在Git找到合并库(取决于此)之后,Git不再关心它了,但是您可能会发现它很有用。 >

找到了current_iterationmapr_autoinit的(单个)合并库(并假设您位于这两个分支之一),这就是Git的工作:

git diff --find-renames <merge-base-hash> current_iteration > /tmp/1
git diff --find-renames <merge-base-hash> mapr_autoinit > /tmp/2

我在这里将这些文件重定向到/tmp个文件中,以便于多次浏览并排或并排查看,这取决于您的文件查看器。由于我不知道您要合并的方向(从什么方向到什么方向),所以我只是给两个文件编号,而不是将它们称为“我们的”和“他们的”。请注意,合并更改步骤无论如何都是对称的。对于每个文件的每次更改,都有四种可能性:

  • 您碰到了台词,但他们没有:Git接您的零钱。
  • 他们碰到了台词,而您却没有:Git接受了他们的找回。
  • 您和他们碰到了界线,但是您进行了相同的更改:Git获取了一份更改。
  • 您和他们触动了界线,但进行了不同的更改:Git声明了合并冲突,并将这两组更改放入工作树文件中。如果您将merge.conflictStyle设置为diff3-我强烈建议这样做-Git还包括基于合并的版本,以向您展示您和他们以< / em>在您和他们进行相冲突的更改之前。

使用合并冲突标记并将通过merge.conflictStyle包含的基本版本设置为diff3来查看结果通常足够。 (特别是,有时它会显示Git具有配对错误更改并认为它们冲突的情况,而实际上这些更改是在其他不冲突的区域进行的。)如果没有,则可能有助于看一下提交图。

有关提交图的更多信息

起作用,但可能很难理解的事情, 1 git log --graph的输出。包括--decorate --oneline选项会很有帮助,对于这种特殊情况,您将希望列出当前分支 2 和要合并的分支的名称。例如,如果您有mapr_autoinit个已签出并打算运行git merge master,则可以运行:

git log --graph --decorate --oneline mapr_autoinit master

Git将尽最大努力以ASCII艺术形式绘制并添加可选的额外颜色来帮助提交图。当然,结果很大程度上取决于图中的内容。这是Linux内核的Git存储库中的一个片段:

* 1ffaddd029c8 (HEAD -> master, tag: v4.18-rc8, origin/master, origin/HEAD) Linux 4.18-rc8
*   a8c199208cd6 Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
|\  
| * 1b3a62643660 x86/boot/compressed/64: Validate trampoline placement against E820
* |   2f3672cbf9da Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
|\ \  
| * | 0a0e0829f990 nohz: Fix missing tick reprogram when interrupting an inline softirq
| * | 80d20d35af1e nohz: Fix local_timer_softirq_pending()
* | |   0cdf6d4607df Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

可以使用它来跟踪自合并基础以来发生的情况。还有更多工具:

git log --graph --decorate --oneline --boundary mapr_autoinit...master
例如,

会向您显示未合并的内容(标记为*的提交),以及(由于--boundary而被合并的 边界提交) (标记为o的提交),但没有比这更深入的图了。

对于非常简单的情况(没有内部分支并重新合并的图形),在三点语法中添加--left-right有时也很有用。对于复杂的情况,每条腿都有许多内部分支与合并操作,--first-parent有时有用,--simplify-by-decoration有时有用。


1 尽管如此,仍然值得细读。如果愿意,可以使用GUI或类似工具来更简洁地绘制图形,但请注意,至少某些Git GUI似乎绘制了不正确的图形( cough various cough webservices < em>咳嗽)。

2 您始终可以使用大写字母HEAD代替当前分支名称。例如,全小写适用于Windows和MacOS上不区分大小写的文件系统,但是养成这种习惯不好。不过,在任何现代Git中,单独的符号@都表示HEAD,因此,如果您愿意,可以使用它代替拼写HEAD。请注意,当使用两点或三点语法(A..BA...B)时,完全省略一个名称​​ 也意味着HEADHEAD..B,{ {1}}和@..B是同一件事的三个拼写。