Git帮助理解 merge 基础冲突

标签 git merge git-merge

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

这是分支结构。

  • 大师
  • 当前_迭代
  • mapr_autoinit

  • Master 已经很老了,并且已经有很长一段时间没有从 current_iteration 中进行更改了。然而,master 通过将其他 base 直接重设到 master 上,直接应用了更改。所以在技术上 master 和 current_iteration 有分歧。我们一直对 current_iteration 进行分支和标记。我看到的问题是,当我从 current_iteration merge 回我的分支时。根据对 current_iteration 的更改,我得到的冲突比应该发生的要多。我能够从 current_iteration 执行 git diff/git apply 并且它应用得很干净。

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

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

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

    这是否是 master 和 current_iteration 出现分歧并且 merge 试图通过重放整个日志来协调 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?



    不。在 merge 基础发现之后重要的是—— merge 基础提交,即——加上两个分支提示提交。两者之间的一切都无关紧要。

    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检查提交图,并使用它来计算 merge 基础提交。请注意 git merge默认情况下运行等效于 git merge-base --all .如果这产生了多个 merge 基础(多个提交哈希 ID),那么您将遇到一种特殊情况。让我们假设您现在没有,但检查一下是个好主意。

    找到了merge base commit,可以查看git log输出(请参阅最后一节)并查看 merge 基础如何与两个分支提示相关联。 Git 并不关心这个——嗯,这不太正确:在 Git 找到 merge 基础(取决于这个)之后,Git 不再关心它——但你可能会发现它很有帮助。

    找到了 current_iteration 的(单个) merge 基础和 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此处的文件以便于多次查看和并排查看或其他方式,具体取决于您的文件查看器。因为我不知道你从哪个方向 merge ——从什么,到什么——我只是给这两个文件编号,而不是称它们为“我们的”和“他们的”。请注意,无论如何,组合更改步骤在很大程度上是对称的。对于每个文件的每次更改,有四种可能性:
  • 您触及了线条而它们没有:Git 接受您的更改。
  • 他们触及了线条而你没有:Git 接受他们的改变。
  • 你和他们触碰了线条,但你做出了同样的改变:Git 复制了一份改变。
  • 你和他们触及了线条,但做了不同的更改:Git 声明了 merge 冲突,并将两组更改放入工作树文件中。如果您设置 merge.conflictStylediff3 ——我强烈推荐这个 ——Git 也包括 merge 基础版本,向你展示你和他们在你之前开始的内容以及他们做出的相互冲突的更改。

  • 查看结果,包含 merge 冲突标记和通过 merge.conflictStyle 包含的基本版本设置为 diff3 ,通常就足够了。 (特别是,它有时会显示 Git 错误配对更改并认为它们冲突的情况,而实际上更改是针对其他不冲突的区域。)如果不是,查看提交图可能会有所帮助。

    关于提交图的更多信息

    确实有效,但很难理解的东西,1 是 git log --graph 的输出.包含 --decorate --oneline 很有帮助选项,对于这种特殊情况,您需要列出当前分支 2 的名称和要 merge 的分支的名称。例如,如果您有 mapr_autoinit checkout 并打算运行 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
    

    人们可以使用它来跟踪自 merge 基础以来发生的事情。还有更多工具:
    git log --graph --decorate --oneline --boundary mapr_autoinit...master
    

    例如,将显示未 merge 的内容(标记为 * 的提交),加上(由于 --boundary )已 merge 的边界提交(标记为 o 的提交),但没有比这更深入的图表。

    对于非常简单的情况——内部分支和重新 merge 并不可怕的图形——添加 --left-right三点语法有时也很有帮助。对于复杂的情况,每条腿都有很多内部分支和 merge 操作,--first-parent有时很有用,而且 --simplify-by-decoration有时很有用。

    1尽管如此,它仍然值得细读。如果您愿意,可以使用 GUI 或类似的工具来更漂亮地绘制图形,但请注意,至少某些 Git GUI 似乎绘制了不正确的图形 (coughvariouscoughwebservicescough)。

    2您始终可以只使用名称HEAD , 全部大写,代替当前分支名称。例如,全小写适用于 Windows 和 MacOS 上不区分大小写的文件系统,但养成这种习惯并不好。孤独的标志 @意味着 HEAD但是,在任何现代 Git 中,如果您愿意,可以使用它而不是拼写 HEAD .请注意,当使用两个或三个点语法( A..BA...B )时,完全省略一个名称也意味着 HEAD :HEAD..B , @..B , 和 ..B是同一事物的三个拼写。

    关于Git帮助理解 merge 基础冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51713876/

    相关文章:

    GIT Rebase 一个协作的分支?

    git - 无法推送到存储库 - 带有 HashMap 的错误

    r - 组合列向量,然后合并到特定格式的数据表中

    swift - 更改swift包文件的文件名

    merge - 有什么方法可以将文档与 Mercurial merge 但从不尝试解决冲突吗?

    python - Pandas:使用 timedelta 合并两个数据帧

    git - git merge 后丢失文件和行

    git - 如何修复错误 merge 中的历史记录

    git - GitHub repos 上的最佳实践,用于 fork 或创建新分支

    git - 奇怪的 git 案例 - git stash 后跟 git stash apply 丢失未提交的数据?