如何解决Git中的合并冲突


4763

如何解决Git中的合并冲突?


30
以下博客文章似乎提供了一个很好的示例,说明了如何处理与Git的合并冲突,这应该使您朝正确的方向前进。处理和避免Git中的冲突
威廉姆斯

4
您可以配置合并工具(kdiff3jebaird.com/2013/07/08/…),然后使用git mergetool。当您在大型开发人员团队中工作时,您总是会遇到合并冲突。
Grady G Cooper

不要忘记,可以通过定期下游合并来缓解大多数合并冲突!
Ant P


8
一个令人着迷的问题:在2008年被问到100%开放时,它到底是什么(关于GUI?关于git命令吗?关于语义?关于推/拉还是只是一般冲突?),根本没有任何暗示。30个答案,所有这些(就快速浏览而言)或多或少地针对不同的diff3和合并工具进行,没有一个被接受。投票最多的答案提到的命令即使在默认git安装中也无法立即使用。今天(2017年),我成功进入了SE初始页,获得了130万的观看次数和数千票的支持。迷人。
AnoE

Answers:


2910

尝试: git mergetool

它会打开一个GUI,逐步引导您解决每个冲突,然后您可以选择如何合并。有时之后需要进行一些手动编辑,但通常仅此一项就足够了。这肯定比手工完成整个事情好得多。

根据@JoshGlover评论:

命令

除非您安装一个GUI,否则不一定打开GUI。git mergetool为我跑步导致vimdiff被使用。您可以安装以下工具之一,而不是使用它:meldopendiffkdiff3tkdiffxxdifftortoisemergegvimdiffdiffuseecmergep4mergearaxisvimdiffemerge

下面是vimdiff用于解决合并冲突的示例过程。基于此链接

第1步:在终端中运行以下命令

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

这会将vimdiff设置为默认的合并工具。

第2步:在终端中运行以下命令

git mergetool

步骤3:您将看到以下格式的vimdiff显示

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

这四个视图是

本地–这是当前分支中的文件

BASE –共同祖先,两次更改之前文件的外观

远程–将文件合并到分支中

已合并-合并结果,这就是保存在存储库中的内容

您可以使用ctrl+ 在这些视图之间导航w。您可以使用ctrl+ w后接来直接进入MERGED视图j

有关此处此处的 vimdiff导航的更多信息

第四步。您可以通过以下方式编辑MERGED视图

如果您想从REMOTE获得更改

:diffg RE  

如果要从BASE获得更改

:diffg BA  

如果您想从本地获得更改

:diffg LO 

步骤5。保存,退出,提交和清理

:wqa 保存并退出vi

git commit -m "message"

git clean 删除由diff工具创建的多余文件(例如* .orig)。


54
仅供参考,git mergetool -y如果您要一次合并很多文件,则可以用来保存一些击键。
davr 2010年

373
好吧,除非您安装一个GUI,否则不一定打开GUI。git mergetool为我跑步导致vimdiff被使用。您可以安装以下工具之一来代替使用它:meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge
乔什·格洛弗

31
好点,乔希。在ubuntu上,我的运气最好,它的三向合并显示也不错。在OSX上,git选择了一个不错的默认值。
彼得·伯恩斯

18
这打开了KDiff3。我绝对不知道如何使用。
David Murdoch

7
您现在也可以使用“超越比较3”(git mergetool -t bc3)。
AzP 2012年

1702

从顶部开始,这是一个可能的用例:

您将进行一些更改,但是,哦,您不是最新的:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

因此,您可以及时了解最新信息并重试,但是会发生冲突:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

因此,您决定看一下更改:

git mergetool

哦,我的,哦,我的上游更改了一些内容,但是只是为了使用我的更改...没有...他们的更改...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

然后我们尝试最后一次

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

-


19
这非常有用,因为我在二进制文件(艺术资产)中存在很多合并错误,并且合并这些错误似乎总是失败,因此我需要始终用新文件覆盖它,而不是“合并”
petrocket 2011年

188
小心!我们和他们的含义相反。--ours ==遥控器。-他们的==当地的。请参阅git merge --help
mmell,2013年

57
就我而言,我确认--theirs =远程存储库,--ours =我自己的本地存储库。它与@mmell注释相反。
Aryo 2013年

24
@mmell显然,仅在重新建立基础上。请参阅this question
Navin

184
伙计们,“我们的”和“他们的”与您是否要合并还是变基础有关。如果你是合并,那么“我们”是指你归并到分支,而“他们”是你在合并分支。当你垫底,然后是“我们”的意思提交你垫底到,而“其”指的是您要重新设置的提交。

736

我发现合并工具很少能帮助我理解冲突或解决方案。通常,在文本编辑器中查看冲突标记并使用git log作为补充通常会更成功。

这里有一些提示:

秘诀一

我发现最好的是使用“ diff3”合并冲突样式:

git config merge.conflictstyle diff3

这将产生如下冲突标记:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

中间部分是共同祖先的样子。这很有用,因为您可以将其与最高和最低版本进行比较,以更好地了解每个分支上的更改,从而更好地了解每个更改的目的。

如果冲突只有几行,那么通常会使冲突非常明显。(知道如何解决冲突是非常不同的;您需要了解其他人的工作。如果您感到困惑,最好将这个人叫到您的房间,以便他们可以看到您的情况。在。)

如果冲突时间更长,则将这三个部分分别剪切并粘贴到三个单独的文件中,例如“ mine”,“ common”和“ theirs”。

然后,我可以运行以下命令来查看引起冲突的两个差异块:

diff common mine
diff common theirs

这与使用合并工具不同,因为合并工具也将包括所有不冲突的差异块。我发现这会分散注意力。

秘诀二

有人已经提到了这一点,但是了解每个差异块背后的意图通常对于理解冲突的来源以及如何解决冲突很有帮助。

git log --merge -p <name of file>

这显示了在共同祖先和您要合并的两个头之间触及该文件的所有提交。(因此,它不包括合并之前两个分支中已经存在的提交。)这可以帮助您忽略显然不是当前冲突因素的diff块。

秘诀三

使用自动化工具验证您的更改。

如果您有自动化测试,请运行那些。如果您有绒毛,请运行它。如果它是一个可构建的项目,则在提交之前进行构建,等等。在所有情况下,您都需要进行一些测试以确保所做的更改不会破坏任何内容。(糟糕,即使没有冲突的合并也可能破坏工作代码。)

秘诀四

未雨绸缪; 与同事沟通。

提前计划并了解其他人正在做什么,可以帮助防止合并冲突和/或帮助及早解决它们-尽管细节仍在脑海中。

例如,如果您知道您和另一个人都在进行将影响同一组文件的不同重构,那么您应该提前进行交谈,以更好地了解每个人的更改类型制造。如果以串行方式而不是并行方式执行计划的更改,则可以节省大量时间和精力。

对于跨越大量代码的重大重构,您应该强烈考虑串行工作:每个人都停止工作在代码的那个区域,而一个人执行完整的重构。

如果您不能连续工作(也许是由于时间紧迫),那么就预期的合并冲突进行交流至少可以帮助您在细节仍在脑海中的同时早日解决问题。例如,如果某个同事在一个星期的时间内进行了一系列破坏性的提交,则您可以选择在该周中每天一次或两次在该同事分支上进行合并/重新设置。这样,如果您发现合并/重新设置冲突,则与等待几周一次将所有内容合并在一起相比,可以更快地解决它们。

秘诀五

如果不确定合并,请不要强行执行。

合并可能会让人感到不知所措,尤其是当存在大量冲突文件且冲突标记覆盖数百行时。通常,在估算软件项目时,我们没有为处理诸如粗糙的合并之类的开销项目留出足够的时间,因此,花数小时来剖析每个冲突似乎是一种真正的拖累。

从长远来看,预先计划并了解其他人正在做什么是预测合并冲突并为自己准备在更少的时间内正确解决它们的最佳工具。


6
diff3选项是合并功能的重要功能。我遇到的唯一显示它的图形用户界面是Perforce的p4merge,可以与Perforce的其他工具(我没有使用过,但是听到过抱怨)分开安装和使用。
alxndr

3
重新尝试导致合并冲突后:$ git log --merge -p build.xml输出:致命:-没有MERGE_HEAD的合并?
Ed Randall

如果我对branch1的一个文件进行了更改,而在branch2中删除了该文件怎么办?我该如何解决合并冲突?有什么办法可以使用git通过保留一个分支的更改来合并它们?
亲爱的

git config merge.conflictstyle diff3- 谢谢你,先生。这真是太神奇了,这使我摆脱了寻找(并支付$$)好的3方式合并GUI的负担。IMO这是更好的方法,因为它显示了公共祖先以及本地/远程,显示了没有GUI的(AFAIK)最后提交日志行。提交肯定可以帮助您确定哪些代码属于哪个分支。
ffxsam

我发现有时diff3冲突样式会导致巨大的diff块,这些块基本上是相同的,而默认值会产生更小,更易于管理的块。不幸的是,我没有可用于错误报告的复制器。但是,如果遇到此问题,您可以考虑暂时关闭该选项。
戴夫·亚伯拉罕斯

348
  1. 确定哪些文件有冲突(Git会告诉您)。

  2. 打开每个文件并检查差异;Git将它们划分边界。希望可以很清楚地看到每个块的版本。您可能需要与提交代码的其他开发人员进行讨论。

  3. 解决了文件中的冲突后git add the_file

  4. 解决所有冲突后,请执行git rebase --continue或完成时Git所说的命令。


38
@Justin认为Git是跟踪内容而不是跟踪文件。然后很容易看到您更新的内容不在存储库中,需要添加。这种思维方式还解释了Git为什么不跟踪空文件夹的原因:尽管从技术上讲它们是文件,但没有任何要跟踪的内容。
Gareth 2010年

7
内容存在,因为存在2版本的内容而发生冲突。因此,“ git add”听起来不正确。如果您只想在冲突解决后提交一个文件(“致命的:在合并过程中无法进行部分提交。”),它就不起作用(git add,git commit)
Dainius

1
是的,从技术上讲,这可以回答所提出的问题,但对不起,这不是可用的答案。什么是做一个分支与另一个相同的?当然,合并将有冲突..
Thufir

5
Thulfir:谁说过使一个分支与另一个分支相同的话?在不同的情况下,您需要合并,而无需“使一个分支与另一个分支相同”。一种是当您完成开发分支后,想要将其更改合并到master分支中;之后,可以删除开发分支。另一个是当您想重新建立开发分支的基础时,以便于最终最终合并到主数据库中。
Teemu Leisti 2012年

4
@JustinGrant git add在索引中暂存文件;它并没有到仓库添加任何东西。git commit将内容添加到存储库。这种用法对于合并很有意义-合并会自动暂存所有可以自动合并的更改;您有责任合并其余的更改,并在完成后将这些更改添加到索引中。
Mark E. Haase 2012年

105

请查看Stack Overflow问题中的答案,中止Git中的合并,尤其是Charles Bailey的答案,该答案显示了如何查看有问题的文件的不同版本,例如,

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

同样,请检查“ git checkout -m”的“ -m”选项-它允许您将不同的苍蝇提取回您的工作区
qneill 2015年

这救了我。分别查看每个文件可以让我记住在每个分支中要做什么。然后,我可以决定选择。
罗默

99

同时更改文件时,会发生合并冲突。这是解决方法。

git 命令行界面

当您陷入冲突状态时,请执行以下简单步骤:

  1. 使用以下命令记录冲突文件的列表git status(在Unmerged paths部分下)。
  2. 通过以下方法之一分别解决每个文件的冲突:

    • 使用GUI解决冲突:(git mergetool最简单的方法)。

    • 要接受远程/其他版本,请使用:git checkout --theirs path/file。这将拒绝您对该文件所做的任何本地更改。

    • 要接受本地/我们的版本,请使用: git checkout --ours path/file

      但是,您必须要小心,因为出于某种原因完成了冲突的远程更改。

      相关:git中“我们的”和“他们的”的确切含义是什么?

    • 手动编辑有冲突的文件,并在<<<<</ 之间寻找代码块,>>>>>然后从上方或下方选择版本=====。请参阅:如何提出冲突

    • 路径和文件名冲突可以通过git add/ 解决git rm

  3. 最后,使用来检查准备提交的文件git status

    如果您仍然有在任何文件Unmerged paths,而你却手动解决冲突,然后让的Git知道你要解决它:git add path/file

  4. 如果成功解决了所有冲突,请通过以下方式提交更改:git commit -a并像往常一样将其推送到远程。

另请参阅: GitHub 的命令行解决合并冲突

有关实用教程,请参阅场景5-修复Katacoda的合并冲突

差异合并

我已经成功使用了DiffMerge,它可以在Windows,macOS和Linux / Unix上直观地比较和合并文件。

它可以以图形方式显示3个文件之间的更改,并允许自动合并(在安全的情况下)并完全控制编辑结果文件。

差异合并

图像来源:DiffMerge(Linux屏幕截图)

只需下载并以以下方式在回购中运行:

git mergetool -t diffmerge .

苹果系统

在macOS上,您可以通过以下方式安装:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

并且可能(如果未提供)您需要在PATH中放置以下额外的简单包装器(例如/usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

然后,您可以使用以下键盘快捷键:

  • - Alt- Up/ Down跳到上一个/下一个变化。
  • - Alt- Left/ Right接受左或右的变化

或者,您可以使用opendiff(Xcode工具的一部分),它可以将两个文件或目录合并在一起以创建第三个文件或目录。


79

如果您要进行频繁的小提交,请先从查看提交注释git log --merge。然后git diff将向您显示冲突。

对于涉及多行的冲突,更容易查看外部GUI工具中发生的情况。我喜欢opendiff-Git还支持vimdiff,gvimdiff,kdiff3,tkdiff,meld,xxdiff,可以直接使用,您可以安装其他git config merge.tool "your.tool"工具:设置您选择的工具,git mergetool合并失败后将在上下文中显示差异。

每次您编辑文件以解决冲突时,git add filename都会更新索引,并且您的差异将不再显示。处理完所有冲突并且其文件已被git add-ed处理后,git commit将完成您的合并。


8
使用“ git add”是这里的真正窍门。您甚至可能不想提交(也许想隐藏),但是必须执行“ git add”才能完成合并。我认为mergetool会为您执行添加操作(尽管不在手册页中),但是如果您手动进行合并,则需要使用“ git add”来完成它(即使您不想提交)。
nobar 2010年

47

请参阅冲突的呈现方式,或者在Git中的git merge文档中了解什么是合并冲突标记。

此外,“ 如何解决冲突”部分介绍了如何解决冲突:

看到冲突后,您可以做两件事:

  • 决定不合并。您唯一需要执行的清除操作是将索引文件重置HEAD为反向2 的提交,并清除2和3对工作树所做的更改。git merge --abort可以用于此。

  • 解决冲突。Git将在工作树中标记冲突。将文件编辑为形状,git add然后将其索引。用于git commit达成交易。

您可以使用多种工具来解决冲突:

  • 使用mergetool。git mergetool启动图形化合并工具,该工具将帮助您完成合并。

  • 看差异。git diff将显示三向差异,突出显示HEADMERGE_HEAD版本之间的变化。

  • 查看每个分支的差异。git log --merge -p <path>将首先显示HEAD版本的差异,然后显示MERGE_HEAD版本。

  • 看看原件。git show :1:filename显示共同祖先,git show :2:filename显示HEAD版本,并git show :3:filename显示MERGE_HEAD版本。

您还可以在Pro Git书的“ 基本合并冲突 ”部分中了解有关合并冲突标记以及如何解决它们的信息。


41

我要么想要我或他们的完整版本,要么想要查看单个更改并为每个更改决定。

完全接受我或他们的版本

接受我的版本(本地版本,我们版本):

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

接受他们的版本(远程的,他们的):

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

如果要对所有冲突文件执行以下操作:

git merge --strategy-option ours

要么

git merge --strategy-option theirs

查看所有更改并单独接受

  1. git mergetool
  2. 查看更改并接受每个版本中的任何一个。
  3. git add <filename>
  4. git commit -m "merged bla bla"

默认值mergetool可在命令行中使用。如何使用命令行合并工具应该是一个单独的问题。

您也可以为此安装可视工具,例如,meld然后运行

git mergetool -t meld

它将打开本地版本(我们的),“基本”或“合并的”版本(合并的当前结果)和远程版本(它们的)。完成后保存合并的版本,git mergetool -t meld再次运行,直到获得“不需要合并文件”,然后转到步骤3和4。


此命令:git checkout --theirs-<文件名>将所有文件更改为它们的文件,而不仅仅是<文件名>
Donato

其实我错了。这只会更新指定的文件。
多纳托

40

对于想要半手动解决合并冲突的Emacs用户:

git diff --name-status --diff-filter=U

显示所有需要解决冲突的文件。

依次打开每个文件,或一次打开所有文件:

emacs $(git diff --name-only --diff-filter=U)

当访问需要在Emacs中进行编辑的缓冲区时,键入

ALT+x vc-resolve-conflicts

这将打开三个缓冲区(mine,他们的缓冲区和输出缓冲区)。通过按“ n”(下一个区域),“ p”(预定义区域)进行导航。按“ a”和“ b”分别将地雷或其区域复制到输出缓冲区。和/或直接编辑输出缓冲区。

完成后:按“ q”。Emacs询问您是否要保存此缓冲区:是的。在完成缓冲区标记后,可通过从末尾运行将其标记为已解析:

git add FILENAME

完成所有缓冲区类型后

git commit

完成合并。


33

奖金:

在上述答案中提到拉取/提取/合并时,我想分享一个有趣且富有成效的技巧,

git pull --rebase

上面的命令是我的git一生中最有用的命令,它节省了很多时间。

推你的新提交的变化到远程服务器之前,尝试git pull --rebasegit pull和手动merge,它会自动同步最新的远程服务器更改(具有取+合并),并将会把您当地的最新承诺在git的日志上。无需担心手动拉/合并。

如有冲突,请使用

git mergetool
git add conflict_file
git rebase --continue

有关详细信息,请访问:http : //gitolite.com/git-pull--rebase


32

简而言之,如果您知道其中一个存储库中的更改并不重要,并且想要解决所有更改以支持另一个存储库,请使用:

git checkout . --ours

解决有利于您的存储库的更改,或者

git checkout . --theirs

解决有利于其他或主存储库的变更。

否则,您将不得不使用GUI合并工具来一步一步地浏览文件,例如合并工具为p4merge,或者写下您已经安装的任何人的名字。

git mergetool -t p4merge

完成文件后,您必须保存并关闭,因此下一个文件将打开。


2
git checkout。-他们 解决了我的问题,谢谢
Ramesh Chand

如果你喜欢解决冲突手动尝试在Visual Studio代码打开文件夹,它标志着每一个内部的矛盾和冲突的色彩线条的文件
穆罕默德·萨利姆·

31

请按照以下步骤修复Git中的合并冲突:

  1. 检查Git状态: git status

  2. 获取补丁集: git fetch(从Git提交中签出正确的补丁)

  3. 签出本地分支(在我的示例中为temp1): git checkout -b temp1

  4. 从master 提取最近的内容: git pull --rebase origin master

  5. 启动mergetool并检查冲突并加以解决...并使用当前分支检查远程分支中的更改: git mergetool

  6. 再次检查状态: git status

  7. 删除由mergetool本地创建的不需要的文件,通常mergetool会创建带有* .orig扩展名的多余文件。请删除该文件,因为它只是重复的文件,并在本地修复更改,然后添加文件的正确版本。 git添加#your_changed_correct_files

  8. 再次检查状态: git status

  9. 将更改提交到相同的提交ID(避免使用新的单独补丁集): git commit --amend

  10. 推送到master分支: git push(到您的Git存储库)


28

共有3个步骤:

  1. 通过命令查找哪些文件导致冲突

    git status
    
  2. 检查文件,您会在其中找到标记为

    <<<<<<<<head
    blablabla
    
  3. 将其更改为所需的方式,然后使用命令进行提交

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

为我工作!谢谢!
Nuwan Jayawardene

在重新设置基准时,必须注意这一点。您应该使用git rebase --continue而不是git commit
Samuel Dauzon '18

27

您可以采用其他方法详细介绍的多种方法来解决合并冲突。

我认为真正的关键是知道更改如何与本地和远程存储库一起流动。关键在于了解跟踪分支。我发现我将跟踪分支视为本地,实际文件目录与定义为源的远程之间的“中间缺失”部分。

我个人已经习惯了两件事来避免这种情况。

代替:

git add .
git commit -m"some msg"

其中有两个缺点-

a)所有新的/更改的文件都会被添加,其中可能包含一些不需要的更改。
b)您无需先查看文件列表。

所以我改为:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

这样,您就可以更仔细地考虑要添加哪些文件,还可以查看列表并在使用编辑器消息时多加考虑。我发现当我使用全屏编辑器而不是该-m选项时,它还可以改善提交消息。

[更新-随着时间的流逝,我将更多时间切换到:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

另外(与您的情况更相关),我尽量避免:

git pull

要么

git pull origin master.

因为pull意味着合并,并且如果您在本地进行了不希望合并的更改,则可以轻松地得到合并的代码和/或不应该合并的代码的合并冲突。

相反,我尝试去做

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

您可能还会发现此帮助:

git branch,fork,fetch,merge,rebase和clone,有什么区别?


嘿,我有点理解您的回答。但是由于我是github合并冲突的新手,所以我认为缺少一些东西。当你碰巧你的本地修改什么git checkout mastergit fetchgit rebase --hard origin/master
Suhaib

我相信您应该添加有关操作的更多详细信息。您在回答中提到了另一个使我感到困惑的示例:我们愿意git add .,它将保存我们的本地修改,以便我们进行跟进git checkout master吗?还是两种不同的情况?
Suhaib

@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option 的用法:git rebase [-i] [选项] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]或:git rebase [-i] [选项] [--exec <cmd>] [--onto <newbase>] --root [<branch>]或:git rebase --continue | -中止| --skip | --edit-待办事项`
likejudo

24

CoolAJ86的答案概括了几乎所有内容。如果您在同一段代码中的两个分支中都有更改,则必须进行手动合并。在任何文本编辑器中打开有冲突的文件,您应该看到以下结构。

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

在删除等号和尖括号的同时,以希望新代码成为的方式选择一种选择或两者的组合。

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

似乎并不总是对我有用,通常最终会显示两个分支之间不同的每个提交,即使使用 --将该路径与命令分开也是如此。

解决此问题的方法是打开两个命令行,一次运行

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

在另一个

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

$MERGED_IN_BRANCH用我合并的分支和[path]冲突的文件代替。此命令将以补丁形式记录..两次()之间的所有提交。如果您像上面命令中那样将一侧留空,则git将自动使用HEAD(在这种情况下,您要合并到的分支)。

这样,您便可以查看在两个分支分开之后,哪些提交提交到了文件中。通常,它更容易解决冲突。


16

使用 patience

令我惊讶的是,没有其他人谈到使用patience合并递归策略解决冲突。对于较大的合并冲突,请使用patience为我提供了很好的结果。这个想法是它将尝试匹配块而不是单个行。

例如,如果您更改程序的缩进,则默认的Git合并策略有时会匹配{属于不同功能的单个花括号。使用以下方法可以避免这种情况patience

git merge -s recursive -X patience other-branch

从文档中:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

与共同祖先的比较

如果您有合并冲突,并且想了解其他人在修改其分支时的想法,则有时将他们的分支直接与公共祖先(而不是我们的分支)进行比较会更容易。为此,您可以使用merge-base

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

通常,您只想查看特定文件的更改:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

在我的情况下,这不能很好地解决合并冲突,因为由于某种原因,它在C#项目中保留了重复的配置行。虽然它比整个文件更友好是不同的,这是我收到
Mathijs塞赫尔斯

15

从2016年12月12日开始,您可以合并分支并解决github.com上的冲突

因此,如果您不想使用旧答案中提供的命令行或任何第三方工具,请使用GitHub的本机工具。

这篇博客文章详细解释了,但是基础是,通过UI“合并”两个分支后,您现在将看到“解决冲突”选项,该选项将带您到允许您处理这些合并冲突的编辑器。

在此处输入图片说明


这不是在问github,所以我不赞成我认为这是一个很差的答案。
mschuett

1
@mschuett是正确的,问题是“如何解决git中的冲突”,而不是“如何解决github中的冲突”。两者之间存在差异,并且已经有太多的人认为git和github是同一件事,所以传播这种感觉的任何事情都是错误的。
Patrick Mevzek '18年

15

如果要从分支(测试)合并到master,可以按照以下步骤操作:

步骤1:前往分行

git checkout test

第二步

git pull --rebase origin master

步骤3:如果有冲突,请转到这些文件进行修改。

步骤4:添加这些更改

git add #your_changes_files

步骤5

git rebase --continue

步骤6:如果仍然存在冲突,请再次返回步骤3。如果没有冲突,请执行以下操作:

git push origin +test

步骤7:然后测试和主机之间没有冲突。您可以直接使用合并。


13

我始终按照以下步骤操作以避免冲突。

  • git checkout master(进入master分支)
  • git pull(更新您的母版以获得最新代码)
  • git checkout -b mybranch(签出一个新的分支并开始在该分支上工作,以便您的主服务器始终保持在主干的顶部。)
  • git添加 AND git commit和git push(更改后在本地分支上)
  • git checkout master(回到您的master。)

现在,您可以执行相同的操作,并维护所需的多个本地分支,并在需要时同时进行git checkout的同时工作。


12

合并冲突可能在不同的情况下发生:

  • 运行“ git fetch”,然后“ git merge”时
  • 运行“ git fetch”,然后“ git rebase”时
  • 运行“ git pull”时(实际上等于上述条件之一)
  • 运行“ git stash pop”时
  • 当您应用git补丁时(提交到要传输的文件的提交,例如通过电子邮件)

您需要安装与Git兼容的合并工具来解决冲突。我个人使用KDiff3,并且发现它非常方便。您可以在此处下载其Windows版本:

https://sourceforge.net/projects/kdiff3/files/

顺便说一句,如果您安装了Git Extensions,则其安装向导中会提供一个选项来安装Kdiff3。

然后设置git configs以使用Kdiff作为其合并工具:

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(请记住将路径替换为Kdiff exe文件的实际路径。)

然后,每次遇到合并冲突时,您只需要运行以下命令:

$git mergetool

然后,它打开Kdiff3,然后首先尝试自动解决合并冲突。大多数冲突将自发解决,您需要手动修复其余的冲突。

这是Kdiff3的样子:

在此处输入图片说明

然后,一旦完成,请保存文件,然后转到有冲突的下一个文件,然后再次执行相同的操作,直到解决所有冲突。

要检查所有内容是否成功合并,只需再次运行mergetool命令,您应该得到以下结果:

$git mergetool
No files need merging

8

这个答案是为像我这样喜欢在编辑器中进行所有操作的VIM用户添加替代方法。


TL; DR

在此处输入图片说明


Tpope提出了这个功能强大的VIM插件fugitive。安装后,您可以运行:Gstatus以检查有冲突的文件并:Gdiff以3种方式打开Git。

在三元合并中,逃犯可以让您以以下方式获取要合并的任何分支的更改:

  • :diffget //2,从原始(HEAD)分支获取更改:
  • :diffget //3,从合并分支获取更改:

完成合并文件后,键入:Gwrite合并的缓冲区。Vimcasts发布了一段精彩的视频,详细介绍了此步骤。



5

git fetch
git checkout 你的分支
git rebase master

在此步骤中,您将尝试使用首选IDE修复冲突。

您可以单击此链接在文件https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/中检查如何解决冲突。

git add
git rebase --continue
git commit --amend
git push origin HEAD:refs / drafts / master(像草稿一样推送)

现在,一切都很好,您会发现自己在gerrit中犯了错误

我希望这将对每个与此问题有关的人有所帮助。


3

如果尚未尝试,请尝试使用Visual Studio Code进行编辑。它的作用是在您尝试合并(并陷入合并冲突)之后。VS代码自动检测到合并冲突。

通过显示对原始内容所做的更改以及您是否应该接受incoming或更改,它可以为您提供很好的帮助。

current change(意味着合并之前的原始版本)'?。

它对我有帮助,它也可以为您服务!

PS:只有在您的代码和Visual Studio Code中配置了git时,它才有效。


2

解决冲突的一种更安全的方法是使用git-mediate(此处建议的常见解决方案是容易出错的恕我直言)。

有关如何使用它的快速介绍,请参见这篇文章


2

对于使用Visual Studio的用户(在我的情况下为2015)

  1. 在VS中关闭项目。尤其是在大型项目中,使用UI进行合并时,VS往往会出现异常。

  2. 在命令提示符下执行合并。

    git checkout target_branch

    git merge source_branch

  3. 然后在VS中打开项目,然后转到Team Explorer-> Branch。现在,出现一条消息,指出合并处于挂起状态,并且在该消息的正下方列出了有冲突的文件。

  4. 单击有冲突的文件,您将可以选择合并,比较,获取源,获取目标。VS中的合并工具非常易于使用。


我在一个非常大的项目上使用VS Code 2017,因此无需关闭该项目。它处理得很好:)
protoEvangelion '17

2

如果您使用intelliJ作为IDE,请尝试通过以下方法将父级合并到分支中

git checkout <localbranch>
git merge origin/<remotebranch>

它将显示所有这样的冲突

A_MBPro:test anu $ git merge origin /自动合并src / test / java / com /.../ TestClass.java CONFLICT(内容):合并src / test / java / com /.../ TestClass.java中的冲突

现在请注意,文件TestClass.java在intelliJ中显示为红色,并且git status将显示

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

在intelliJ中打开文件,它将包含以下部分:

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

HEAD是本地分支上的更改,而origin /是远程分支上的更改。在这里保留您需要的东西,然后删除不需要的东西。那是

   git add TestClass.java
   git commit -m "commit message"
   git push

2

我正在使用Microsoft的Visual Code解决冲突。它非常简单易用。我在工作区中保持项目处于打开状态。它可以检测并突出显示冲突,此外还提供GUI选项以选择我要保留的HEAD或传入的任何更改。 在此处输入图片说明

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.