解决Git合并冲突,以便在拉取期间进行更改

如何解决git合并冲突以支持拉动更改?

我想从工作树中删除所有冲突的更改,而不必经历与git mergetool的所有冲突,同时保持所有无冲突的更改。最好是,我想在拉取时执行此操作,而不是之后。

1310432 次浏览

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

git merge --strategy-option theirs

oursThis option forces conflicting hunks to be auto-resolved cleanly byfavoring our version. Changes from the other tree that do notconflict with our side are reflected to the merge result.
This should not be confused with the ours merge strategy, which doesnot even look at what the other tree contains at all. It discardseverything the other tree did, declaring our history contains all thathappened in it.
theirsThis is opposite of ours.

注意:正如手册页所说,“我们的”合并策略选项与“我们的”合并战略非常不同。

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

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

git pull -X theirs

如果你已经处于冲突状态…

git checkout --theirs path/to/file

好的,想象一下我刚刚进入的场景:

你尝试merge,或者cherry-pick,你被阻止了

$ git cherry-pick 1023e24error: could not apply 1023e24... [Commit Message]hint: after resolving the conflicts, mark the corrected pathshint: 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.phpgit add path/to/the/conflicted_file.php

反过来(用你的版本覆盖传入的版本)是

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

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

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

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

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

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

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

git checkout --theirs .git add .

如果你想做相反的事情:

git checkout --ours .git add .

这是相当激烈的,所以确保你真的想在这样做之前把所有东西都擦掉。

请不要这样做,有时会不工作

git检出--我们的路径/到/文件

git检出--他们的路径/到/文件

我做了这个,假设头是我们的MERGE_HEAD是他们的

git checkout HEAD -- path/to/file

或:

git checkout MERGE_HEAD -- path/to/file

在我们这样做之后,我们很好:

git add .

如果你想了解更多,在这里看到托雷克的精彩帖子:git签出--our不会从未合并文件列表中删除文件

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

这基本上会做一个假合并。它将记录一个新的合并提交两个分支都作为父母,但它甚至不会看分支它会简单地记录为合并的结果当前分支中的确切代码。

$ git merge -s ours mundo

合并由“我们的”战略。

$ git diff HEAD HEAD~

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

这通常可以用来欺骗Git认为稍后进行合并时,分支已经合并。例如,说你分支了一个发布分支,并对它做了一些工作您将希望在某个时候合并回您的主分支。在与此同时,master上的一些错误修复需要反向移植到您的发布分支。您可以将错误修复分支合并到发布中分支并合并-s我们的同一分支到您的主分支(即使修复已经存在),所以当您稍后合并再次释放分支,错误修复没有冲突。

如果我想让master反映新主题分支的变化,我发现这种情况很有用。我注意到-Xher在某些情况下不会在没有冲突的情况下合并…例如

$ 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 our策略合并到master中,这将创建仅为topicFoo状态的假提交。##合并我们的主节点

检查创建的合并提交

$ git log

现在检查主分支

$ git checkout master

将主题分支合并回来,但这一次使用-Xthe的递归策略,现在将为您提供一个具有topicFoo状态的主分支。

$ git merge -X theirs topicFoo

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

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

如果您想简单地忽略存储库中对文件的任何本地修改,例如在应该始终是源镜像的客户端上,请运行此操作(将master替换为您想要的分支):

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

它是如何工作的?#0做#1但没有合并。然后#2使您的工作树与上一次提交相匹配。您对存储库中文件的所有本地更改都将是丢弃,但新的本地文件将被单独保留。

VS Code(集成Git)IDE用户:

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

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

类似地,您可以为接受所有两者,接受所有当前等,等其他选项执行此操作

我有一个长期运行的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-versiongit checkout next-version .# files removed, now add the deletions to the commitgit add .# still have files that were added on develop; in my case they are all in web/git rm -r web

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

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

git merge --abortgit pull -X theirs

git checkout --ours/theirs并不专门解决冲突。它从ours/theirs中签出(获取整个文件)。

假设我们有一个文件foo,其中有两个提交/分支/树/之类的更改。如果他们引入了冲突,以及修改,我们希望使用ours解决冲突-那么使用checkout --ours foo将丢弃引入冲突的更改,还有修改。

使用SED

使用他们的解决方案:

sed -i -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' foo

  • -i就地修改文件,
  • /^<<<<<<</,/^=======/d删除<<<<<<<=======之间的所有内容(我们的)
  • /^>>>>>>>/d删除剩余的冲突标记
  • -e为SED指定多个模式
  • foo文件

使用我们的解决方案:

sed -i -e '/^<<<<<<</d' -e '/^=======/,/^>>>>>>>/d' foo

我做了一个脚本,你可以打电话给git resolve -o/-t/-b

创建自定义合并工具

您可以创建自定义合并工具。基于上述sed脚本,您可以在git-config中添加类似的内容:

[mergetool "ours"]cmd = "sed -i -e '/^<<<<<<</d' -e '/^=======/,/^>>>>>>>/d' -- $MERGED"

并称之为git mergetool --tool=ours

在使用smerge-mode的Emacs中,要解决所有使用我的或他们的冲突标记,我们可以定义:

(defun aj/smerge-keep-mine-all ()""(interactive)(save-excursion(beginning-of-buffer)(while (ignore-errors 'user-error (progn (smerge-next) t))(smerge-keep-mine))))
(defun aj/smerge-keep-other-all ()""(interactive)(save-excursion(beginning-of-buffer)(while (ignore-errors 'user-error (progn (smerge-next) t))(smerge-keep-other))))

已经解决了。通过以下简单步骤解决所有冲突。

git fetch && git reset --hard origin/master
git pull -X theirs
git pull origin master

如果您想接受所有当前更改并忽略任何传入的更改,您可以这样做:

git merge [branch] --strategy-option ours

[branch]应该替换为您要合并到当前分支的分支的名称。

相反,如果您知道要覆盖任何当前更改并接受传入更改的所有冲突,则可以使用theirs策略:

git merge [branch] --strategy-option theirs

接受远程更改(theirs),如果有冲突,您会收到以下错误:

fatal: Not possible to fast-forward, aborting.

因此,您可能希望通过快进来拉取并接受他们的更改:

$ git pull -X theirs --ff

尽管这里已经有了很好的答案,但我想发布这个答案来记录如何解决Visual Studio中的所有合并冲突(以我们更改为例)。

相反,如果您想接受这个问题中询问的传入更改(他们更改),只需将下面步骤6中的ours替换为theirs。就这么简单。


总结一下我在这里做的事情:

合并开发到当前分支,如果有任何合并冲突,从当前分支获取版本。

(完成后,我将创建一个PR,最终将更改从我的分支推送到开发)。


步骤1

通过转到“管理分支机构”并双击您的分支名称来签出要合并dev的分支。在我的情况下,它是feature\InterimBranchToDev2-AshK

步骤2:

右键单击dev并单击Merge 'dev' into 'feature/InterimBranchToDev2-AshK'

步骤3:

你会看到大量的合并冲突!😲

现在右键单击这些文件并单击Keep Current (feature/InterimBranchToDev2-AshK)非常乏味,所以让我们Abort并使用命令行处理这个问题。

步骤4:

命中Abort

步骤5:

打开cmd

步骤6:

输入git merge --strategy-option ours --no-commit dev并输入

这是什么意思:“将开发合并到当前分支,如果有任何合并冲突,从当前分支获取版本,也不要提交合并”。

这将是输出:Automatic merge went well; stopped before committing as requested

步骤7:

现在转到Visual Studio,冲突得到了很好的处理,您可以输入消息并提交: