代码之家  ›  专栏  ›  技术社区  ›  Chris Hinshaw

Git有助于理解合并基冲突

  •  12
  • Chris Hinshaw  · 技术社区  · 6 年前

    我在未修改的文件上遇到冲突。合并时单行更改的文件发生冲突。我开始了解可能发生的事情,但仍然无法解决问题。

    这是分支结构。

    • 主人
      • 当前迭代
        • 映射程序自动初始化

    Master已经很老了,在相当长的一段时间内没有改变当前的_迭代。然而,通过将其他基础直接重设为master,master已经直接应用了更改。因此,技术上的掌握和当前的_迭代出现了分歧。我们一直在分支和标记当前的_迭代。我看到的问题是,当我从当前的迭代合并回分支时。根据对当前迭代的更改,我得到的冲突比应该发生的冲突多得多。我能够从当前的迭代中执行git diff/git apply,并且它应用得很干净。

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

    从我最近几天看到的情况来看,如果我将master合并到当前的_迭代中,提交并将当前的_迭代合并回master中似乎是合乎逻辑的。这可能会解析我的分支合并基以指向更新的版本。

    也有可能我可以停止跟踪主人。我试着用 git config --unset branch.master.merge; git config --unset branch.master.remote 停止跟踪主人,但这并没有解决我的问题。

    这是一个主迭代和当前的_迭代已经分离的问题吗?merge试图通过重放整个日志来协调合并?

    这里还有更多细节。我现在提出一个新问题,这个问题要具体得多。我将更新一个有效的答案或删除旧的取决于哪个是首选。

    Git merge resulting in unreasonable conflicts

    1 回复  |  直到 6 年前
        1
  •  13
  •   torek    6 年前

    我从未找到 git show-branch 输出对我自己非常有用,我不确定它打算如何使用,也不知道其他人可能如何成功使用它。

    也有可能,我可以停止跟踪主人。。。

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

    这是一个主迭代和当前的_迭代已经分离的问题吗?merge试图通过重放整个日志来协调合并?

    不,重要的是 之后 合并基查找只是合并基提交,即加上两个分支提示提交。介于两者之间的一切都无关紧要。

    但是当我检查时 git merge-base current_iteration mapr_autoinit 我看到这个版本是最新的,很可能不会有冲突。

    这通常是开始的方法,因为 git merge-base 检查提交图,并使用它计算合并基提交。请注意 git merge 默认情况下,运行等效于 git merge-base --all . 如果这产生 不止一个 合并基(多个提交哈希ID),您有特殊情况。让我们假设你现在没有,但最好检查一下。

    找到合并基提交后,可以查看 git log 输出(见最后一节)并查看合并基与两个分支提示的关系。吉特不在乎这个,这不太对: 在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 这里的文件便于多次查看和并排查看,具体取决于您的文件查看器。因为我不知道你是从哪个方向来的,所以我只是给这两个文件编号,而不是叫它们“我们的”和“他们的”。请注意 合并更改 步骤基本上是对称的。对于每个文件的每个更改,有四种可能:

    • 你碰了线他们没有:吉特替你找钱。
    • 他们碰了线,你却没碰:吉特替他们找钱。
    • 你和他们接触了这些行,但是你做了同样的更改:Git接受了更改的一个副本。
    • 您和他们接触了这些行,但做了不同的更改:Git声明了一个合并冲突,并将这两组更改放入工作树文件中。如果你设置 merge.conflictStyle diff3 高度地 建议这个git也包含merge-base版本,以显示您和他们 开始于 在你和他们做出冲突的改变之前。

    通过合并冲突标记和包含的基本版本查看结果 合并.冲突样式 设置为 差异3 ,是 通常 足够了。(特别是,它有时会显示Git 错配 更改并认为它们是冲突的,而实际上这些更改是对其他不冲突的区域的更改。)如果不是,查看提交图可能会有所帮助。

    关于提交图的更多信息

    一些 工作,但是很难理解, git log --graph . 包括 --decorate --oneline 选项,对于这种特殊情况,您需要列出当前分支的名称 以及你打算合并的分支。例如,如果你有 映射程序自动初始化 退房并打算逃跑 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 有时是有用的。


    尽管如此,它仍然值得细读。如果愿意,可以使用图形用户界面(GUI)或类似的工具来更漂亮地绘制图形,但要注意,至少有些Git GUI似乎绘制了不正确的图形( 咳嗽 各种各样的 咳嗽 网络服务 咳嗽 ).

    你总是可以用这个名字 HEAD ,以所有大写字母代替当前分支名称。例如,所有小写字母都适用于Windows和MacOS上不区分大小写的文件系统,但养成这种习惯并不好。孤军奋战 @ 方法 头部 不过,在任何现代Git中,如果您愿意,可以使用它而不是拼写 头部 . 注意,当使用二点或三点语法时( A..B A...B ),完全省略一个名称 方法 头部 : HEAD..B , @..B ,和 ..B 是同一件事的三个拼写。