【问题标题】:Resolving a Git conflict with binary files解决与二进制文件的 Git 冲突
【发布时间】:2010-09-21 15:23:41
【问题描述】:

我一直在 Windows 上使用 Git (msysgit) 来跟踪我一直在做的一些设计工作的更改。

今天我一直在另一台 PC 上工作(使用远程 repo brian),现在我正在尝试将今天完成的编辑合并回我笔记本电脑上的常规本地版本。

在我的笔记本电脑上,我使用git pull brian master 将更改拉入我的本地版本。除了主要的 InDesign 文档之外,一切都很好 - 这显示为冲突。

PC 上的版本 (brian) 是我想保留的最新版本,但我不知道是什么命令告诉 repo 使用这个版本。

我尝试将文件直接复制到我的笔记本电脑上,但这似乎破坏了整个合并过程。

谁能指出我正确的方向?

【问题讨论】:

    标签: git merge-conflict-resolution


    【解决方案1】:

    如果二进制文件不仅仅是 dll 或者可以直接编辑的东西,例如图像或混合文件(并且您不需要丢弃/选择一个文件或另一个)真正的合并可能是这样的:

    我建议搜索一个针对你的二进制文件是什么的差异工具,例如,有一些免费的用于图像文件的工具

    并比较它们。

    如果没有用于比较文件的 diff 工具,那么如果您有 bin 文件的原始生成器(也就是说,存在编辑器它...就像 blender 3d 一样,您可以手动检查这些文件,还可以查看日志,并询问其他人您应该包含哪些内容) 并使用https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge 输出文件

    $ git show :1:hello.blend > hello.common.blend
    $ git show :2:hello.blend > hello.ours.blend
    $ git show :3:hello.blend > hello.theirs.blend
    

    【讨论】:

      【解决方案2】:

      此过程是为了在您向 Github 提交拉取请求后解决二进制文件冲突:

      1. 所以在 Github 上,您发现您的拉取请求与二进制文件存在冲突。
      2. 现在回到本地计算机上的同一个 git 分支。
      3. 您 (a) 再次重新制作/重新构建此二进制文件,并且 (b) 将生成的二进制文件提交到同一个 git 分支。
      4. 然后你将这个相同的 git 分支再次推送到 Github。

      在 Github 上,根据您的拉取请求,冲突应该会消失。

      【讨论】:

        【解决方案3】:

        我的情况似乎是一个错误......使用 git 2.21.0

        我做了一个拉...它抱怨二进制文件:

        warning: Cannot merge binary files: <path>
        Auto-merging <path>
        CONFLICT (content): Merge conflict in <path>
        Automatic merge failed; fix conflicts and then commit the result.
        

        然后这里的任何答案都没有导致任何有意义的输出。

        如果我查看我现在拥有的文件...它是我编辑的那个。如果我这样做:

        git checkout --theirs -- <path>
        git checkout --ours -- <path>
        

        我得到输出:

        Updated 0 paths from the index
        

        我仍然有我的文件版本。如果我 rm 然后结帐,它会改为 1,但它仍然给我我的文件版本。

        git mergetool 说

        No files need merging
        

        和 git status 说

            All conflicts fixed but you are still merging.
            (use "git commit" to conclude merge)
        

        一个选项是undo the commit... 但我很不幸,我有很多提交,而这个糟糕的提交是第一个。我不想浪费时间重复这一点。

        所以要解决这个疯狂的问题:

        我刚刚跑了

        git commit
        

        这会丢失远程版本,并且可能会浪费一些空间来存储额外的二进制文件......然后

        git checkout <commit where the remote version exists> <path>
        

        这给了我远程版本

        然后再次编辑文件...然后提交并推送,这可能再次意味着使用另一个二进制文件副本浪费空间。

        【讨论】:

        • 就我而言,在尝试git checkout --ours &lt;path&gt; 后,我收到了Updated 0 paths from the index 。我已经用git add &lt;path&gt; 命令修复了这个问题,它的作用是一样的。
        【解决方案4】:

        我使用 Git Workflow for Excel - https://www.xltrail.com/blog/git-workflow-for-excel 应用程序来解决我的大多数与二进制文件相关的合并问题。这个开源应用程序可以帮助我高效地解决问题,而无需花费太多时间,让我可以毫不费力地挑选正确的文件版本。

        【讨论】:

          【解决方案5】:

          你也可以用

          解决这个问题
          git mergetool
          

          这会导致git 创建冲突二进制文件的本地副本并在其上生成您的默认编辑器:

          • {conflicted}.HEAD
          • {conflicted}
          • {conflicted}.REMOTE

          显然,您无法在文本编辑器中有效地编辑二进制文件。相反,您将新的{conflicted}.REMOTE 文件复制到{conflicted} 而不关闭编辑器。然后,当您关闭编辑器 git 时,您会看到未修饰的工作副本已更改,并且您的合并冲突以通常的方式解决。

          【讨论】:

          • 如果文件很大或者您根本不想冒险在文本编辑器中打开二进制文件,您可以在合并工具提示符 ("Hit return to start merge resolution tool") 处按 ctrl+c,然后 git 会将多余的文件留在原处。然后您可以修改它们或将它们合并到外部工具中(对于像 LibreOffice/OpenOffice/MSWord 这样的二进制文档格式很有用)并将结果保存回原始文件名。通知 git 冲突已解决,git add 原始文件名,然后您可以完成合并提交。
          【解决方案6】:

          git checkout 在这种情况下接受 --ours--theirs 选项。因此,如果您有合并冲突,并且您知道您只想要正在合并的分支中的文件,您可以这样做:

          $ git checkout --theirs -- path/to/conflicted-file.txt
          

          使用该版本的文件。同样,如果你知道你想要你的版本(不是被合并的那个),你可以使用

          $ git checkout --ours -- path/to/conflicted-file.txt
          

          【讨论】:

          • 在使用 --ours 之前,我必须在文件上运行 'git reset HEAD path/to/conflicted-file.txt',否则它似乎没有效果。
          • @Zitrax 您在运行git checkout --ours 后是否对文件进行了比较?手册页建议(恕我直言) checkout --ours/--theirs 将从“都已修改,需要合并”列表中删除更改并将其添加到索引中,我认为这是不正确的。我相信您需要在结帐后运行git add
          • 注意:你仍然想做“git add conflicted-file.txt”和“git commit”。方便的是,当我尝试它时,提交消息中预先填充了有关冲突的注释。
          • “你正在合并的分支”的措辞非常接近“你正在合并的分支”,我认为只是去掉介词会更好:“你正在合并的分支”,这也将反映 git 命令(即git merge branch_name)。
          • 在解释这个主题时总是缺少一些重要的点。当做 rebase 而不是合并时,--their--ours 的含义被交换,即 --their == 当前签出的分支和 --ours 是分支,通常是远程分支,或者你是路径规范试图合并到当前分支。 [space]--[space] 选项消除了分支名称和路径规范之间的路径规范的歧义,它们恰好以相同的名称存在(例如,现有的分支名称是“abc”,并且存在一个名为“abc”的目录)。
          【解决方案7】:

          我遇到了两种在 Windows 上使用 Git 管理二进制文件差异/合并的策略。

          1. Tortoise git 允许您根据文件扩展名为不同文件类型配置差异/合并工具。见 2.35.4.3。差异/合并高级设置http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html。这种策略当然依赖于可用的合适的差异/合并工具。

          2. 使用 git 属性,您可以指定一个工具/命令将二进制文件转换为文本,然后让您的默认 diff/merge 工具执行此操作。见http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes。这篇文章甚至给出了一个使用元数据来区分图像的例子。

          我有两种策略来处理软件模型的二进制文件,但我们使用了乌龟 git,因为配置很简单。

          【讨论】:

            【解决方案8】:

            mipadi 的回答不太适合我,我需要这样做:

            git checkout --ours path/to/file.bin

            或者,保留正在合并的版本:

            git checkout --theirs path/to/file.bin

            然后

            git add path/to/file.bin

            然后我能够再次执行“git mergetool”并继续下一个冲突。

            【讨论】:

              【解决方案9】:

              来自git checkout docs

              git checkout [-f|--ours|--theirs|-m|--conflict=&lt;style&gt;] [&lt;tree-ish&gt;] [--] &lt;paths&gt;...

              --ours
              --theirs
              从索引中检查路径时,请检查阶段 #2 (ours) 或 #3 (theirs) 以获取未合并的路径。

              由于先前的合并失败,索引可能包含未合并的条目。默认情况下,如果您尝试从索引中签出此类条目,则签出操作将失败并且不会签出任何内容。使用-f 将忽略这些未合并的条目。可以使用--ours--theirs 将合并特定侧的内容从索引中签出。使用-m,可以丢弃对工作树文件所做的更改,以重新创建原始的冲突合并结果。

              【讨论】:

                【解决方案10】:

                您必须手动解决冲突(复制文件),然后像这样提交文件(无论是复制还是使用本地版本)

                git commit -a -m "Fix merge conflict in test.foo"
                

                Git 通常会在合并后自动提交,但当它检测到无法自行解决的冲突时,它会应用它发现的所有补丁,其余的留给您手动解决和提交。 Git Merge Man PageGit-SVN Crash Coursethis 博客条目可能会阐明它应该如何工作。

                编辑:看下面的帖子,其实不用自己复制文件,但是可以用

                git checkout --ours -- path/to/file.txt
                git checkout --theirs -- path/to/file.txt
                

                选择所需文件的版本。仅当您想要混合使用两个版本时,才需要复制/编辑文件。

                请将 mipadis 的答案标记为正确的答案。

                【讨论】:

                • 谢谢。我不确定是否有某种内置方法可以将文件标记为“正确”文件。解释了为什么我找不到不存在的命令!
                • 是的,这有点不直观 - 像 git resolve 这样的东西会很好,但也是一个额外的步骤......
                【解决方案11】:

                要通过将版本保留在当前分支中来解决(忽略要合并的分支中的版本),只需添加并提交文件:

                git commit -a
                

                要通过使用您正在合并的分支中的版本覆盖当前分支中的版本来解决问题,您需要先将该版本检索到您的工作目录中,然后添加/提交它:

                git checkout otherbranch theconflictedfile
                git commit -a
                

                Explained in more detail

                【讨论】:

                • 我更喜欢这个变体而不是公认的答案,因为它更直观,特别是考虑到那些“--ours”和“--theirs”的含义在变基的情况下被交换了。跨度>
                【解决方案12】:

                我遇到了一个类似的问题(想要拉出一个包含一些在合并时会导致冲突的二进制文件的提交),但是遇到了一个可以完全使用 git 完成的不同解决方案(即不必手动复制文件) .我想我会把它放在这里,这样至少下次我需要它时我能记住它。 :) 步骤如下所示:

                % git fetch
                

                这会从远程存储库中获取最新的提交(您可能需要指定远程分支名称,具体取决于您的设置),但不会尝试合并它们。它在 FETCH_HEAD 中记录提交

                % git checkout FETCH_HEAD stuff/to/update
                

                这会获取我想要的二进制文件的副本,并用从远程分支获取的版本覆盖工作树中的内容。 git 不会尝试进行任何合并,因此您最终会得到来自远程分支的二进制文件的精确副本。完成后,您可以像往常一样添加/提交新副本。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-05-18
                  • 2010-09-11
                  • 2011-10-05
                  • 1970-01-01
                  • 2015-09-23
                  • 2011-03-31
                  • 1970-01-01
                  • 2017-02-08
                  相关资源
                  最近更新 更多