在拉动期间解决Git合并冲突以支持其更改

san*_*mai 1104 git git-merge git-merge-conflict

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

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

Pas*_*res 1011

git pull -s recursive -X theirs <remoterepo or other repo>
Run Code Online (Sandbox Code Playgroud)

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

git pull -X theirs
Run Code Online (Sandbox Code Playgroud)

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

git checkout --theirs path/to/file
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这里的`-s recursive`是多余的,因为这是默认的合并策略.所以你可以将它简化为`git pull -X theirs`,这基本上相当于[`git pull --strategy-option theirs`](http://stackoverflow.com/a/10697551/456814). (37认同)
  • 小心`git checkout --thethe path/to/file`.在rebase期间使用它并获得意想不到的结果.在doc中找到解释:_注意在git rebase和git pull --rebase期间,我们和他们的可能会出现交换; --ours给出了分支中的版本,更改被重新定义,而 - 他们给出了分支中的版本,用于保存正在重新定位的工作._ (19认同)
  • 请注意,`git checkout --theirs/ - our path`手册页指出它适用于**未合并路径**.因此,如果路径中没有冲突,则它已经合并,此命令将不执行任何操作.当您想要整个子文件夹的"他们的"版本时,这可能会出现问题.所以在这种情况下,使用`git checkout MERGE_HEAD path`或使用commit hash会更安全. (9认同)
  • *注意*: `git checkout --theirs path/glob` 不能解决使用我们/他们的冲突。它从“我们的/他们的”中获取整个文件。如果存在不冲突的更改,它们将被丢弃。 (8认同)
  • 如果我这样做,我最终会回到"合并"状态.然后我可以`git merge --abort`再试一次,但每次我最终都会发生合并.......我知道,虽然这可能会推动我的上游,所以也许这会导致这种情况发生? (3认同)
  • 如果存在冲突,`git pull -X theirs`会创建合并提交(例如,如果另一个提交者将`git push -f`运行到远程).如果你不想要合并提交,请运行`git fetch && git reset --hard origin/master`. (3认同)
  • `git checkout --他们的。` (2认同)

Ikk*_*kke 937

您可以使用递归的"他们的"策略选项:

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.
Run Code Online (Sandbox Code Playgroud)

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

  • 还有`git checkout --theirs`来操作一个冲突的文件 (224认同)
  • @ThorSummoner在这种情况下,有git checkout --thepath/of/file.这样,您不必手动查找正确的哈希. (54认同)
  • 如果您已处于冲突解决状态,则此方法无效.在这种情况下,我认为最好的解决方法是`git checkout <ref to theirs> - /conflicted.file`; 然后`git add`他们的变化. (46认同)
  • @Ikke如果你问我,那基本上应该是它自己的答案(以及接受的答案). (8认同)
  • 这是更详细的解释:http://lostechies.com/joshuaflanagan/2010/01/29/how-to-resolve-a-binary-file-conflict-with-git/ (2认同)
  • `git merge --strategy-option 他们的 BRANCH_THEIRS` 仍然对我产生冲突...... (2认同)

小智 419

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

git checkout --theirs .
git add .
Run Code Online (Sandbox Code Playgroud)

如果你想做相反的事情:

git checkout --ours .
git add .
Run Code Online (Sandbox Code Playgroud)

这是非常激烈的,所以在做之前确保你真的想要像这样擦除所有东西.

  • 或者,不要使用`.`并指定文件来代替您要结帐的点.大概不那么"激烈",正是你想要做的事情. (45认同)
  • 如果文件已从其他分支中删除,则此操作无效:'<file>'没有其版本 (9认同)
  • 使用`git add -u`代替跳过不受版本控制的文件. (6认同)
  • 假设案例,文件中的三个更改,一个冲突,两个没有冲突,此解决方案是否会应用非冲突更改并将冲突更改解决到我们的解决方案中?或者只需要我们的版本忽略他们的非冲突更改? (6认同)
  • @pedromarce `git checkout --ours` 接受我们的**所有**更改,包括非冲突的更改。对此要小心。 (5认同)
  • 如果可以的话,我会更多地投票,时不时地继续回到这个答案。 (4认同)
  • “ours”和“irs”指的是“HEAD”以及正在合并到“HEAD”中的任何内容,即签出的当前提交。将“我们的”视为“当前”,将“他们的”视为“即将到来的”,而不是像你的工作与其他人的工作一样。我们的/他们的是什么将取决于您是否通过存储/变基/合并解决冲突。*注意*`git checkout --ours/--theirs`只选择一个版本并**完全丢弃**另一个版本。IE。这个答案可能不是你想要的。请参阅我的答案,了解如何仅放弃冲突的更改 (4认同)
  • “--theirs”是否意味着“即将发生的变化”?而“--ours”的意思是“当前更改”? (3认同)
  • @tonix,总是从偏执的 Linus Torvalds 保护 linux 免受外部更改的角度来解释 git 术语。如果您应用这种思维方式,那么“他们的”意味着正在合并的更改(或合并候选者),“我们的”意味着将接收合并的一方(将被更新的分支)。请注意,所有这些都严格基于 git merge 命令的方向(而不是您更大的目的或本地/原始设置等)。我讨厌“我们的/他们的”术语,因为它在“git merge”中具有技术含义,这可能与听起来相反。 (3认同)
  • 值得一提的是,像大多数 git 操作一样,您可以将其应用于路径,例如“git checkout --theirs wp-content/languages/”,它将仅从传入分支获取该路径下的文件,而其余部分保持不变。 (2认同)

The*_*ith 219

好吧,想象一下我刚才的情景:

你尝试了一个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'
Run Code Online (Sandbox Code Playgroud)

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

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php
Run Code Online (Sandbox Code Playgroud)

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

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,我在网上很难找到这个答案.

  • 请注意,如果在`checkout`和`add`之间执行`git status`,该文件仍显示为"两者都被修改". (14认同)
  • 您知道是否有办法对所有处于冲突状态的文件执行此操作?如果是这样,这将是对你的答案的一个很好的扩展。 (2认同)
  • 我这样做:`git reset --hard`然后`git pull [远程服务器名称] [分支名称] -Xtheirs`(撤消合并然后将新的东西拉到我的东西之上)-不知道这是什么想。 (2认同)

Dan*_*scu 34

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

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

如果你想简单地忽略对repo文件的任何本地修改,例如在应该始终是原始镜像的客户端上,运行它(用master你想要的分支替换):

git fetch && git reset --hard origin/master
Run Code Online (Sandbox Code Playgroud)

它是如何工作的?git fetch确实git pull没有合并.然后git reset --hard使您的工作树与最后一次提交匹配.对repo中文件的所有本地更改都将被丢弃,但新的本地文件将保持不变.

  • +1 - `git fetch &amp;&amp; git reset --hard {remote}/{branch}` 解决了我的问题。我需要完全放弃自己的更改,转而支持分支的“他们的”状态,但是“git pull -X 他们的”被一些移动/重命名的文件阻塞了。谢谢! (4认同)

s.h*_*sam 20

更新2024年!

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

git merge [branch] --strategy-option ours
Run Code Online (Sandbox Code Playgroud)

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

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

git merge [branch] --strategy-option theirs
Run Code Online (Sandbox Code Playgroud)


小智 19

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

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}
Run Code Online (Sandbox Code Playgroud)

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

git diff --name-only --diff-filter=U | xargs git checkout master
Run Code Online (Sandbox Code Playgroud)

  • 这很好,意味着如果您手动解决一些问题(并执行“git add”),那么您可以通过此方法批量解决其余问题。`git checkout --ours` / `git checkout --theirs` 也很有用。 (2认同)

Cer*_*vEd 19

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"
Run Code Online (Sandbox Code Playgroud)

并称之为git mergetool --tool=ours

合并样式

请注意,还有其他非标准合并样式,如diff3@Stavroszdiff3在评论中指出的那样。冲突标记的数量在 git 中也没有硬编码为 7。我相信这主要只是默认设置,我记得它是可以配置的。

sed可以调整基本脚本以适用于所有配置。

  • 我开始在 Git 邮件列表上讨论它以寻求可能的解决方案:https://public-inbox.org/git/3e1548ab-5e20-9555-bd10-d6cbf2ffbce4@gmail.com/ (3认同)
  • 这个答案强调了“git merge --theirs|--ours”所做的一个关键和微妙的点,即从他们或我们的分支中选择整个文件。目前 git 中没有内置的命令行选项来解决_仅_冲突部分,选择他们的或我们的。这只能通过手动编辑来完成。一些合并工具(例如 Tortoise、P4、kdf3 等)会有所帮助。这个答案中的“sed”选项很方便,并且是最接近命令行选项的选项。 (2认同)

Nic*_*s D 17

请注意,有时这不起作用:

git checkout --ours path/to/file

要么

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

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

git checkout HEAD -- path/to/file
Run Code Online (Sandbox Code Playgroud)

要么:

git checkout MERGE_HEAD -- path/to/file
Run Code Online (Sandbox Code Playgroud)

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

git add .
Run Code Online (Sandbox Code Playgroud)

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


Lee*_*iam 12

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

git merge --abort
git pull -X theirs
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,我使用了 ```git merge &lt;your-branches&gt; -X 他们的``` (3认同)
  • `git pull -r origin main -X 他们的` (3认同)
  • 这不允许您为单个文件选择合并策略。对于此类要求,请使用“git checkout --theirs &lt;file&gt;”。 (2认同)

Sri*_*tha 11

VS Code(集成Git)IDE用户:

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

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming
Run Code Online (Sandbox Code Playgroud)

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

  • 这似乎仅适用于单个文件,但不适用于所有有冲突的文件。 (2认同)

小智 7

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

git checkout --theirs .
git checkout --ours.
Run Code Online (Sandbox Code Playgroud)

  • 我将如何在每个冲突块的基础上执行此操作?上面的代码适用于文件级别,丢弃冲突文件可能具有的任何非冲突块。 (2认同)

Amo*_*rin 5

\n

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

\n\n

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

\n\n
$ git merge -s ours mundo\n
Run Code Online (Sandbox Code Playgroud)\n\n

由“我们的”策略进行的合并。

\n\n
$ git diff HEAD HEAD~\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

这通常很有用,可以让 Git 认为在稍后进行合并时已经合并了一个分支。例如,假设您从一个发布分支分支出来,并对其进行了一些工作,您希望在某个时候合并回主分支。与此同时,master 上的一些错误修复需要向后移植到您的发布分支中。您可以将 bugfix 分支合并到release分支中,也可以将 -s 我们的同一个分支合并到您的 master 分支中(即使修复已经存在),因此当您稍后再次合并release分支时,会有错误修正没有冲突。

\n
\n\n

如果我希望 master 反映新主题分支的更改,我发现这种情况很有用。我注意到 -Xtheirs 在某些情况下不会在没有冲突的情况下合并...\ne.g。

\n\n
$ git merge -Xtheirs topicFoo \n\nCONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这种情况下,我找到的解决方案是

\n\n
$ git checkout topicFoo\n
Run Code Online (Sandbox Code Playgroud)\n\n

从 topicFoo 开始,首先使用 -s ours 策略合并到 master 中,这将创建一个假提交,它只是 topicFoo 的状态。\n$ git merge -s ours master

\n\n

检查创建的合并提交

\n\n
$ git log\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在检查主分支

\n\n
$ git checkout master\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
$ git merge -X theirs topicFoo\n
Run Code Online (Sandbox Code Playgroud)\n


归档时间:

查看次数:

707965 次

最近记录:

6 年 前