解决二进制文件的Git冲突


464

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

今天,我一直在另一台PC上(带有远程repo brian)工作,现在我试图将今天完成的编辑合并到笔记本电脑上的常规本地版本中。

在我的笔记本电脑上,我曾经习惯于git pull brian master将更改引入本地版本。除了主要的InDesign文档之外,其他一切都很好-这显示为冲突。

PC(brian)上的版本是我要保留的最新版本,但我不知道是什么命令告诉仓库使用此版本。

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

谁能指出我正确的方向?

Answers:


853

git checkout在这种情况下接受--oursor --theirs选项。因此,如果您遇到合并冲突,并且知道只希望合并中的分支中的文件,则可以执行以下操作:

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

使用该文件的版本。同样,如果您知道要使用的版本(而不是要合并的版本),则可以使用

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

47
在使用--ours之前,我必须在文件上运行'git reset HEAD path / to / conflicted-file.txt',否则它似乎没有效果。
Zitrax 2011年

6
@Zitrax运行后是否比较了文件git checkout --ours?手册页建议(IMHO)结帐-我们/-他们会将更改从“已修改,需要合并”列表中删除,并将其添加到索引中,我认为这是不正确的。我相信您将需要git add在结帐后运行。
蒂姆·基廷

15
注意:您仍然想要执行“ git addflicted-file.txt ”和“ git commit”。方便地,当我尝试时,在提交消息中预先填充了有关冲突的注释。
爱德华·福尔克

2
“您要合并的分支”的措词很危险地接近“您要合并的分支”,我认为只掉介词会更好:“您要合并的分支”,这也将反映git命令(即git merge branch_name)。
andrybak

13
在此主题的解释中始终缺少几个要点。在进行基础替换而不是合并时,将替换--their和的含义--ours,即--their ==当前已签出的分支,而--ours是该分支,通常是远程分支,或者是您尝试合并到当前分支中的路径规范科。该[space]--[space]选项消除了分支名称和路径规范之间的路径规范的歧义,而路径规范恰好都存在相同的名称(例如,现有的分支名称为“ abc”,而目录名为“ abc”)。
BoiseBaked

147

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

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

Git通常在合并后自动提交,但是当它检测到冲突无法自行解决时,它将应用它找出的所有修补程序,其余的由您解决并手动提交。在Git的合并手册页中,针对Git SVN速成班博客条目可能揭示它是如何工作的一些情况。

编辑:请参阅下面的文章,您实际上不必自己复制文件,但可以使用

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

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

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


1
感谢那。我不确定是否有某种内置方式将文件标记为“正确”文件。说明为什么我找不到不存在的命令!
凯文·威尔逊,

是的,那有点不直观-像git resolve这样的东西会很好,但也将是一个额外的步骤……
VolkA

120

您也可以使用

git mergetool

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

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

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


8
如果文件很大,或者根本不想冒用文本编辑器打开二进制文件的风险,则可以在mergetool提示符(“ Hit return to start merge resolution tool”)上按ctrl + c,而git会将多余的文件保留在原处。然后,您可以修改它们或将它们合并到外部工具(对于LibreOffice / OpenOffice / MSWord等二进制文档格式很有用),然后将结果保存回原始文件名。要通知git解决了冲突,请git add使用原始文件名,然后可以完成合并提交。
费利克斯

18

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

git commit -a

要通过合并当前分支中的版本来覆盖当前分支中的版本,请首先将该版本检索到工作目录中,然后添加/提交该版本:

git checkout otherbranch theconflictedfile
git commit -a

详细解释


1
我更喜欢此变体,而不是公认的答案,因为它更直观,尤其是考虑到在重新定基的情况下,“-我们的”和“-它们的”的含义会互换。
安东尼·哈奇金斯

11

mipadi的答案对我来说不太有效,我需要这样做:

git checkout-我们的路径/到/file.bin

或者,保持版本合并在其中:

git checkout-他们的路径/到/file.bin

然后

git添加路径/到/ file.bin

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


6

来自git checkout文档

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

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

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


4

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

% git fetch

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

% git checkout FETCH_HEAD stuff/to/update

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


4

此过程用于解决向Github提交拉取请求后的二进制文件冲突:

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

在Github上,应您的请求,冲突应该消失。


这正是我需要的过程
冯慧芳

2

如果二进制文件不仅是dll或可以直接编辑的图像(例如图像)或混合文件(并且您不需要删除/选择一个文件或另一个文件),那么真正的合并将是:

我建议搜索针对您的二进制文件的差异工具,例如,有一些免费的图像文件例如

并比较它们。

如果没有用于比较文件的差异工具,则如果您具有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


1

我遇到了两种在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。该文章甚至提供了一个使用元数据来比较图像的示例。

我有两种策略都可以使用软件模型的二进制文件,但是由于配置简单,因此我们使用了tortoise git。



0

我的情况似乎是一个错误....使用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)

一种选择是撤消提交 ……但是我很不幸,我有很多提交,而这个不好的是第一个。我不想浪费时间重复。

为了解决这种疯狂:

我刚跑

git commit

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

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

这给了我远程版本

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


就我而言,在尝试git checkout --ours <path>接收之后Updated 0 paths from the index 。我已经用git add <path>命令修复了这一点,它的作用相同。
Andriy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.