【问题标题】:How to automatically resolve multiple git conflicts under some path?如何自动解决某个路径下的多个 git 冲突?
【发布时间】:2020-12-14 19:29:54
【问题描述】:

在将分支 Source 合并到 Target 时,我遇到了大约 1K 的冲突,我注意到以下情况:

  1. 路径 MyRepo\SomeFolder\A\ 下的所有冲突文件都应从 Source 分支中选取。例如。 "MyRepo\SomeFolder\A\File1.txt, MyRepo\SomeFolder\A\File2.script"
  2. 路径 MyRepo\SomeFolder\B\ 下的所有冲突文件都应从 Target 分支中选取。例如。 "MyRepo\SomeFolder\B\File3.csproj, MyRepo\SomeFolder\B\File4.txt"
  3. 应通过从源和目标中挑选部分代码来手动解决来自其他路径的少量文件。

Bullet 3 我可以手动解决。存储桶 1. 和 2. 中的冲突数量巨大。有没有办法运行批处理脚本/命令,可以解决 1/2 中的所有冲突?

类似(伪代码):

Foreach file in path
    if file is conflicted/ contains '<<<<'
       pick it from Source and resolve that conflict(or Target, depending on scenario 1 or 2)

另外,如果有 gui 这样做,那就更好了,但我敢肯定我要求太多了 :)

【问题讨论】:

  • 想法:如果一次提交可以分解为一个目录的提交,你可以只使用我们的/他们的。当然,您最终会遇到多个合并提交...

标签: git merge-conflict-resolution git-merge-conflict


【解决方案1】:

这里需要一种对来自每个冲突合并的三个输入文件调用git merge-file 的方法。 (这是 Mercurial 现有工具比 Git 更好的一个领域,因为它内置了这个。)

有了这样的工具,你会:

  • 列出文件名
  • 将列表分为三部分:“自动我们的”、“自动他们的”和“手动”
  • 使用此工具(运行 git merge-file 与您指定的选项,但在这三个输入文件上)与 --ours--theirs 酌情使用,然后 git add-s 结果
  • 手动解决剩余文件。

此工具几乎存在:git mergetool 包含正确调用该工具所需的所有机制,但git mergetool 本身相当复杂。将其修改为所需的工具很难。

可以通过依靠git show 从 Git 的索引中提取三个文件中的每一个来构建应该存在的工具的模仿。鉴于冲突文件 F,目前在 Git 的索引中有三个 F 副本。 F 的合并基础版本在:1:<em>F</em>--ours 版本在:2:<em>F</em>--theirs 版本在:3:<em>F</em>。但是,这可能无法正确解释文件重命名操作。像 mergetool 代码那样使用git checkout-index 可能会更好。

要获取未合并文件的列表,请使用git ls-files -u。 (注意这会启用--stage。)

要运行git merge-file,请将每个文件中三个输入的签出(即可用的纯文本文件)副本提供给它。添加所需的合并选项(--ours--theirs;如果您正在使用该工具,则允许--union 也可能是合理的)以自动解决冲突。然后,考虑做git mergetool 所做的其余部分:自动git add 处理结果。

为此编写实际工具留作练习。

【讨论】:

    【解决方案2】:

    您可以使用git checkout --ours/--theirs -- directory/path

    它只会更改磁盘上文件的内容冲突文件,并且仍然会将文件列为冲突文件,因此您可以检查内容是否符合您的喜好,如果您发现您选择了错误,请运行git checkout --[other-side]一边。

    如果你意识到你需要返回一个文件或目录的冲突内容,你可以运行:

    git checkout -m -- file/or/directory
    

    如果你的意思是来源和目标:

    # from branch Target :
    git checkout Target
    
    # you are merging Source :
    git merge Source
    

    然后:

    • Source--theirs
    • Target--ours

    要运行的命令是:

    git checkout --theirs -- SomeFolder\A
    git checkout --ours -- SomeFolder\B
    

    如果您对 SomeFolder\A 的内容感到满意,请运行 git add SomeFolder\A 以删除冲突状态并将其暂存以进行提交。

    正如@torek 指出的那样,缺点是您将无法再访问--theirs/--ours/-m 版本。

    【讨论】:

      【解决方案3】:

      您应该能够使用git-resolve-conflict 做您想做的事。这是jakub.g 编写的git merge-file 的小包装器。您可以将其作为脚本签出

      https://github.com/jakub-g/git-resolve-conflict

      或使用安装它

      npm install -g git-resolve-conflict
      

      它只是一个小 bash 脚本,可让您使用给定策略更轻松地解决特定文件的合并冲突 (cmp.this SO answer)。

      要以特定方式对子目录的所有文件执行此操作,您可以执行以下操作。

      for ITEM in $(git diff --name-only --diff-filter=U | grep `SomeFolder/A/); do git-resolve-conflict --theirs $ITEM; done
      for ITEM in $(git diff --name-only --diff-filter=U | grep `SomeFolder/B/); do git-resolve-conflict --ours $ITEM; done
      

      如果您使用 unix-y shell,这也应该在 Windows 下工作,例如 Git Bash

      【讨论】:

        猜你喜欢
        • 2013-03-01
        • 2014-04-01
        • 2020-03-02
        • 1970-01-01
        • 2014-09-17
        • 1970-01-01
        • 2018-05-15
        • 1970-01-01
        • 2018-04-19
        相关资源
        最近更新 更多