解决Git合并冲突以利于拉动期间的更改


1224

我该如何解决git merge冲突以利于更改?

基本上,我需要从工作树中删除所有有冲突的更改,而不必git mergetool在保持所有无冲突更改的同时经历所有冲突。最好在拉动时这样做,而不是在以后。



2
从远程复制了git pull。我可以强迫它覆盖而不是报告冲突吗?您可以在那里看到相同的解决方案。
Dan Dascalescu 2014年

3
@DanDascalescu接受的答案不会回答此问题,因此显然不是重复的。另外,另一个问题是非常模棱两可的:很难说出要问什么。总而言之,我不同意你的看法。您对此有何意义?
sanmai 2014年

2
@sanmai您有两个答案-您接受了其中一个。您能否更好地解释您对答案的期望,以及在此处需要多少详细信息?
爱德华·汤姆森

2
@EdwardThomson好吧,实际上我正在考虑为第一个答案提供这个声誉,但是如果您要问,我可能会等一下,看看是否有更好的答案
sanmai 2014年

Answers:


1213
git pull -s recursive -X theirs <remoterepo or other repo>

或者,简单地,对于默认存储库:

git pull -X theirs

如果您已经处于冲突状态...

git checkout --theirs path/to/file

40
请注意,-s recursive这是多余的,因为这是默认的合并策略。因此,您可以将其简化为git pull -X theirs,基本上等同于git pull --strategy-option theirs

5
如果这样做,我最终会回到MERGING状态。然后git merge --abort,我可以重试,但是每次结束合并时,我都会发生。…我知道一个基础已经推到了我的上游,那也许是造成这个的原因吗?
约翰

22
请注意git checkout --theirs path/to/file。在重新设置基准时使用它,并获得了意外的结果。在文档中找到解释:请注意,在git rebase和git pull --rebase期间,我们和他们的可能会互换;--ours提供更改所基于的分支的版本,而--thes提供保留要重新构建的工作的分支的版本。
Vuk Djapic '17

10
请注意,git checkout --theirs/--ours path手册页指出它适用于未合并的路径。因此,如果路径中没有冲突,则说明该命令已经合并,将不会执行任何操作。例如,当您想要整个子文件夹的“其”版本时,这可能会出现问题。因此,在这种情况下,执行git checkout MERGE_HEAD path或使用提交哈希会更安全。
fsw

4
git pull -X theirs如果存在冲突(例如,如果另一个提交者跑到git push -f远程),则创建一个合并提交。如果您不希望合并提交,请改为运行git fetch && git reset --hard origin/master
Dan Dascalescu

985

您可以使用递归“他们的”策略选项

git merge --strategy-option theirs

男人

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

注:由于该男子页称,“我们的”合并的策略选项是从“我们”合并完全不同的策略


下面是更详细的解释:lostechies.com/joshuaflanagan/2010/01/29/...
mPrinC

227
git checkout --theirs可以对单个有冲突的文件进行操作
DVD 2014年

48
如果您已经处于冲突解决状态,则此方法不起作用。在这种情况下,我认为解决的最好办法是git checkout <ref to theirs> -- the/conflicted.file; 然后git add他们的变化。
ThorSummoner

54
@ThorSummoner在这种情况下,有git checkout-它们的路径/文件/文件。这样,您不必手动查找正确的哈希。
Ikke 2014年

8
@Ikke如果您问我,那基本上应该是它自己的答案(以及当时公认的答案)。
ThorSummoner 2014年

472

如果您已经处于冲突状态,并且只想接受他们所有的状态:

git checkout --theirs .
git add .

如果要执行相反的操作:

git checkout --ours .
git add .

这太剧烈了,因此请确保您确实要在执行此操作之前先将所有内容清除掉。


47
或者,不要使用.和指定文件来代替您要检出的点。少“大刀阔斧”,而确切地说是您想做什么。
manroe 2015年

10
如果文件已从另一个分支中删除,这将不起作用:'<file>'没有其版本
Japster24

3
如果可以的话,将投票更多,请不时地回到这个答案。
tarikki 2016年

6
git add -u而是使用它跳过不受版本控制的文件。
Sudipta Basak

3
假设情况是文件中的三个更改,一个冲突,两个不冲突,那么此解决方案是否会应用非冲突性更改并解决我们的冲突性更改?还是只需要我们的版本来忽略与它们无冲突的更改?
pedromarce

222

好了,想象一下我刚刚遇到的情况:

您尝试使用merge或可能cherry-pick会用停止

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

现在,您查看冲突的文件,而您确实不想保留所做的更改。在上面的例子中,文件在我的IDE自动添加的换行符上发生冲突。要撤消更改并接受更改,最简单的方法是:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

相反(用您的版本覆盖传入的版本)是

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

令人惊讶的是,我在网络上找不到这个答案。


15
请注意,如果git statuscheckout和之间执行add,则文件仍显示为“两者均已修改”。
主教

您是否知道是否可以对所有处于冲突状态的文件执行此操作?如果是这样,那将是对您的答案的一个很好的扩展。
德鲁·诺阿克斯

2
我这样做: git reset --hard 然后 git pull [remote server name] [branch name] -Xtheirs(撤消合并,然后将新内容放到我的内容之上)-不知道这是否是您想要的。
ssaltman

38

git pull -X theirs答案可能创建一个丑陋的合并提交,或发出

错误:您对以下文件的本地更改将被合并覆盖:

如果您只想忽略对存储库中文件的任何本地修改,例如在应该始终是源镜像的客户端上,请运行此命令(master用所需的分支替换):

git fetch && git reset --hard origin/master

它是如何工作的?git fetch可以,git pull但是没有合并。然后git reset --hard使您的工作树与最后一次提交匹配。您对存储库中文件的所有本地更改将被丢弃,但是新的本地文件将被保留。


1
+1- git fetch && git reset --hard {remote}/{branch}解决了我的问题。我需要完全放弃自己的更改,以支持分支的“其”状态,但是git pull -X theirs在某些移动/重命名的文件上却被阻塞了。谢谢!
Ivaylo Slavov

22

git merge之后,如果您遇到冲突并且想要自己或他们的

git checkout --theirs .
git checkout --ours .

我将如何在每个冲突块的基础上执行此操作?上面的内容在文件级别上起作用,抛出冲突文件可能具有的所有非冲突块。
Jani

21

要解决与特定分支中的版本的所有冲突:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

因此,如果您已经处于合并状态,并且想要保留冲突文件的主版本:

git diff --name-only --diff-filter=U | xargs git checkout master

对于在Windows上无法访问管道xargs的人,这是如何翻译的?
tsemer '16

它不会完全跳过您的更改吗?即使那些不处于冲突状态的?
Valentin Heinitz '18

这就是我最终要做的。不幸的是,随后必须使用一个git cherry-pick --continue 一个git commit --allow-empty命令,以提交这些变化,而且似乎没有系统之后所需要的命令,这使得自动化这样的痛苦。我目前正在通过测试.git/COMMIT_EDITMSG文件的存在来解决此问题,但这似乎很脆弱而且很脆弱,而且我还不确定该文件是否总是可以工作。
康拉德·鲁道夫

这很好,这意味着如果您手动解决一些问题(并执行git add),则可以通过此解决大量问题。git checkout --ours/ git checkout --theirs也很有用。
rcoup

18

请不要这样,有时这是行不通的

git checkout-我们的路径/到/文件

要么

git checkout-他们的路径/到/文件

我是这样做的,假设HEAD是我们的,MERGE_HEAD是他们的

git checkout HEAD -- path/to/file

要么:

git checkout MERGE_HEAD -- path/to/file

完成此操作后,我们会很好:

git add .

如果您想了解更多,请在这里查看torek的精彩文章: git checkout-我们不会从未合并的文件列表中删除文件


12

VS Code(集成Git)IDE用户:

如果要接受冲突文件中的所有传入更改,请执行以下步骤。

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

同样,您可以对其他选项执行操作,例如“ 全部接受”,“全部接受当前”等,


2
这似乎仅适用于单个文件,但不适用于所有有冲突的文件。
Yoryo

1

我有一个长期运行的next-version分支机构,对已更改的develop文件,在两个分支机构中不同位置添加的文件进行大量删除,等等。

我想将next-version分支的全部内容都带入develop,所有这些都需要进行一次合并提交。

以上对我有用的命令的组合是:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

这不是一个新的答案,只是结合了许多答案中的一部分,部分是为了确保您可能需要所有这些答案。


1

如果您已经处于冲突状态,并且不想一一签出路径。你可以试试

git merge --abort
git pull -X theirs

-1

https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

这基本上会进行伪合并。它将记录两个分支都作为父级的新合并提交,但它甚至不会查看您要合并的分支。它将简单地记录合并的结果作为当前分支中的确切代码。

$ git merge -s ours mundo

通过“我们的”策略合并。

$ git diff HEAD HEAD~

您可以看到我们所在的分支与合并结果之间没有任何区别。

在以后进行合并时,从根本上诱骗Git认为分支已被合并通常会很有用。例如,假设您从一个发布分支分支出来,并且已经对其进行了一些工作,那么您将需要在某个时候合并回您的主分支。同时,master上的一些错误修正需要回移植到您的发行分支中。您可以将bugfix分支合并到release分支中,也可以将-s我们的相同分支合并到您的master分支中(即使已存在此修复程序),因此当您以后再次合并release分支时,bugfix不会产生冲突。

我希望管理员掌握新主题分支的更改,这对我很有用。我注意到-Xtheirs在某些情况下不会合并而不会发生冲突...例如

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

在这种情况下,我发现的解决方案是

$ git checkout topicFoo

从topicFoo开始,首先使用-s ours策略合并到master中,这将创建仅是topicFoo状态的假提交。$ git merge -s我们的主人

检查创建的合并提交

$ git log

现在结帐master分支

$ git checkout master

将主题分支合并回去,但是这次使用-Xtheirs递归策略,这将为您提供状态为topicFoo的主分支。

$ git merge -X theirs topicFoo
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.