Git 有助于理解合并基础冲突
Git help to understand merge-base conflicts
我在未修改的文件上遇到冲突。合并时一行变化的文件冲突。我开始了解可能发生的事情,但仍然无法解决问题。
这是分支结构。
- 大师
- current_iteration
- mapr_autoinit
Master 已经很老了,current_iteration 已经有一段时间没有变化了。然而,master 已经通过将其他基础直接变基到 master 来直接应用它。所以技术上master和current_iteration已经分道扬镳了。我们一直在分支并标记 current_iteration。我看到的问题是,当我从 current_iteration 合并回我的分支时。根据对 current_iteration 的更改,我得到的冲突比应该发生的要多得多。我能够从 current_iteration 执行 git diff / git apply 并且它应用得很干净。
当我在 mapr-autoinit 上 运行 a 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 但这并没有解决我的问题。
这是 master 和 current_iteration 分歧的问题,merge 试图通过重播整个日志来协调合并吗?
这里还有更多细节。现在我要提出一个新问题,因为这个问题要具体得多。我将使用有效答案更新两者或删除旧答案,具体取决于首选答案。
Git merge resulting in unreasonable conflicts
我自己从未发现 git show-branch
输出非常有用,我不确定它的用途,也不确定其他人如何成功使用它。
Also is it possible that I could stop tracking master ...
这个无关紧要。重要的是实际的提交图。任何分支的上游都独立于提交图。
Is this a problem where the master and current_iteration have diverged and merge is trying to reconcile the merge by replaying the entire log?
没有。 在 合并基础发现之后重要的只是合并基础提交,即加上两个分支提示提交。两者之间的一切都是无关紧要的。
However when I check git merge-base current_iteration mapr_autoinit
I see that the version is very recent and most likely would not have conflicts.
这通常是开始的方式,因为 git merge-base
检查提交图,并使用它来计算合并基础提交。请注意,默认情况下 git merge
运行 等同于 git merge-base --all
。如果这会产生 多个 合并基础(多个提交哈希 ID),则情况特殊。假设您暂时不这样做,但最好检查一下。
找到合并基础提交后,您可以查看 git log
输出(参见上一节)并了解合并基础与两个分支提示的关系。 Git 不关心这个——好吧,这不太对:在 Git 找到合并基础后 (取决于此),Git 不再关心它——但您可能会发现它有帮助。
找到 current_iteration
和 mapr_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
文件,以便于多次查看并并排查看或其他任何内容,具体取决于您的文件查看器。因为我不知道你要合并哪个方向——从什么方向,到什么方向——我只是给这两个文件编号,而不是称它们为 "ours" 和 "theirs"。请注意,无论如何,合并更改 这一步基本上是对称的。对于每个文件的每次更改,有四种可能性:
- 您触摸了线条,但它们没有:Git 取走您的零钱。
- 他们碰了线而你没有:Git找了他们。
- 你和他们触及了线条,但你做了同样的更改:Git 复制了一份更改。
- 你和他们触及了界限,但做了不同的更改:Git 声明合并冲突,并将两组更改放入工作树文件中。如果您将
merge.conflictStyle
设置为 diff3
——我 高度 推荐这个——Git 也包括 merge-base 版本,向您展示您和他们在您之前开始,他们做出了相互矛盾的更改。
查看结果,使用合并冲突标记和通过 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 艺术中绘制,并添加可选的额外颜色来帮助提交图。当然,结果在很大程度上取决于图表中的内容。这是 Git 存储库中 Linux 内核的片段:
* 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 似乎绘制了不正确的图形(咳嗽各种咳嗽webservices咳嗽).
2您始终可以只使用全大写字母的名称 HEAD
代替当前分支名称。例如,全小写适用于 Windows 和 MacOS 上不区分大小写的文件系统,但养成这种习惯并不好。但是,一个单独的符号 @
在任何现代 Git 中都表示 HEAD
,所以如果您愿意,可以使用它而不是拼写 HEAD
。请注意,当使用两个或三个点语法(A..B
和 A...B
)时,完全省略一个名称 also 表示 HEAD
:HEAD..B
、@..B
和..B
是同一事物的三种拼写。
我在未修改的文件上遇到冲突。合并时一行变化的文件冲突。我开始了解可能发生的事情,但仍然无法解决问题。
这是分支结构。
- 大师
- current_iteration
- mapr_autoinit
- current_iteration
Master 已经很老了,current_iteration 已经有一段时间没有变化了。然而,master 已经通过将其他基础直接变基到 master 来直接应用它。所以技术上master和current_iteration已经分道扬镳了。我们一直在分支并标记 current_iteration。我看到的问题是,当我从 current_iteration 合并回我的分支时。根据对 current_iteration 的更改,我得到的冲突比应该发生的要多得多。我能够从 current_iteration 执行 git diff / git apply 并且它应用得很干净。
当我在 mapr-autoinit 上 运行 a 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 但这并没有解决我的问题。
这是 master 和 current_iteration 分歧的问题,merge 试图通过重播整个日志来协调合并吗?
这里还有更多细节。现在我要提出一个新问题,因为这个问题要具体得多。我将使用有效答案更新两者或删除旧答案,具体取决于首选答案。
Git merge resulting in unreasonable conflicts
我自己从未发现 git show-branch
输出非常有用,我不确定它的用途,也不确定其他人如何成功使用它。
Also is it possible that I could stop tracking master ...
这个无关紧要。重要的是实际的提交图。任何分支的上游都独立于提交图。
Is this a problem where the master and current_iteration have diverged and merge is trying to reconcile the merge by replaying the entire log?
没有。 在 合并基础发现之后重要的只是合并基础提交,即加上两个分支提示提交。两者之间的一切都是无关紧要的。
However when I check
git merge-base current_iteration mapr_autoinit
I see that the version is very recent and most likely would not have conflicts.
这通常是开始的方式,因为 git merge-base
检查提交图,并使用它来计算合并基础提交。请注意,默认情况下 git merge
运行 等同于 git merge-base --all
。如果这会产生 多个 合并基础(多个提交哈希 ID),则情况特殊。假设您暂时不这样做,但最好检查一下。
找到合并基础提交后,您可以查看 git log
输出(参见上一节)并了解合并基础与两个分支提示的关系。 Git 不关心这个——好吧,这不太对:在 Git 找到合并基础后 (取决于此),Git 不再关心它——但您可能会发现它有帮助。
找到 current_iteration
和 mapr_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
文件,以便于多次查看并并排查看或其他任何内容,具体取决于您的文件查看器。因为我不知道你要合并哪个方向——从什么方向,到什么方向——我只是给这两个文件编号,而不是称它们为 "ours" 和 "theirs"。请注意,无论如何,合并更改 这一步基本上是对称的。对于每个文件的每次更改,有四种可能性:
- 您触摸了线条,但它们没有:Git 取走您的零钱。
- 他们碰了线而你没有:Git找了他们。
- 你和他们触及了线条,但你做了同样的更改:Git 复制了一份更改。
- 你和他们触及了界限,但做了不同的更改:Git 声明合并冲突,并将两组更改放入工作树文件中。如果您将
merge.conflictStyle
设置为diff3
——我 高度 推荐这个——Git 也包括 merge-base 版本,向您展示您和他们在您之前开始,他们做出了相互矛盾的更改。
查看结果,使用合并冲突标记和通过 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 艺术中绘制,并添加可选的额外颜色来帮助提交图。当然,结果在很大程度上取决于图表中的内容。这是 Git 存储库中 Linux 内核的片段:
* 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 似乎绘制了不正确的图形(咳嗽各种咳嗽webservices咳嗽).
2您始终可以只使用全大写字母的名称 HEAD
代替当前分支名称。例如,全小写适用于 Windows 和 MacOS 上不区分大小写的文件系统,但养成这种习惯并不好。但是,一个单独的符号 @
在任何现代 Git 中都表示 HEAD
,所以如果您愿意,可以使用它而不是拼写 HEAD
。请注意,当使用两个或三个点语法(A..B
和 A...B
)时,完全省略一个名称 also 表示 HEAD
:HEAD..B
、@..B
和..B
是同一事物的三种拼写。