ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

git pull from remote.. can I force it to overwrite rather than report conflicts? 的副本您可以在那里看到相同的解决方案。
@DanDascalescu 接受的答案没有回答这个问题,所以很明显它不是重复的。另外,另一个问题非常模糊:很难说出所问的内容。总而言之,我不能同意你的看法。你在这有什么意义?
@sanmai您有两个答案-您接受了其中一个。您能否更好地解释您对答案的期望以及您希望在这里获得多少详细信息?
@EdwardThomson 好吧,实际上我想为第一个答案提供这个声誉,但如果你问,我可能会等着看是否有更好的答案出现

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

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

git pull -X theirs

If you're already in conflicted state...

git checkout --theirs path/to/file

请注意,此处的 -s recursive 是多余的,因为这是默认的合并策略。因此,您可以将其简化为 git pull -X theirs,它基本上等同于 git pull --strategy-option theirs
如果我这样做,我最终会回到 MERGING 状态。然后我可以 git merge --abort 再试一次,但每次我都会发生合并。 ......我知道一个变基被推到我的上游,所以也许这是造成这种情况的原因?
小心使用 git checkout --theirs path/to/file。在 rebase 期间使用它并得到了意想不到的结果。在文档中找到解释:请注意,在 git rebase 和 git pull --rebase 期间,我们的和他们的可能会出现交换; --ours 给出了更改被重新定位到的分支的版本,而 --theirs 给出了保存正在被重新定位的工作的分支的版本。
请注意,git checkout --theirs/--ours path 手册页声明它适用于未合并的路径。所以如果路径没有冲突,它已经被合并了,这个命令什么也不做。例如,当您想要整个子文件夹的“他们的”版本时,这可能会出现问题。所以在这种情况下,做 git checkout MERGE_HEAD path 或使用提交哈希会更安全。
如果存在冲突(例如,如果另一个提交者将 git push -f 运行到远程),git pull -X theirs 创建一个合并提交。如果您不想合并提交,请改为运行 git fetch && git reset --hard origin/master
N
N T

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

git merge --strategy-option theirs

man

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/…
git checkout --theirs 对单个冲突文件进行操作
如果您已经处于冲突解决状态,这将不起作用。在这种情况下,我认为最好的解决方法是git checkout <ref to theirs> -- the/conflicted.file;然后 git add 他们的更改。
@ThorSummoner 在这种情况下,有 git checkout --theirs path/of/file。这样,您不必手动查找正确的哈希值。
@Ikke 如果您问我,那基本上应该是它自己的答案(以及当时公认的答案)。
l
lots-to-learn

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

git checkout --theirs .
git add .

如果你想做相反的事情:

git checkout --ours .
git add .

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


或者,不要使用 . 并指定文件来代替您要签出的点。不那么“激烈”大概是你想做的事。
如果文件已从另一个分支中删除,这将不起作用:'' 没有它们的版本
请改用 git add -u 跳过不受版本控制的文件。
假设情况,一个文件中的三个更改,一个冲突,两个不冲突,此解决方案是否会应用非冲突更改并解决我们的冲突更改?还是只需要我们的版本而忽略他们的不冲突更改?
@pedromarce git checkout --ours 接受我们的所有 更改,包括非冲突更改。小心点。
T
Theodore R. Smith

好的,想象一下我刚才所处的场景:

您尝试 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

令人惊讶的是,我无法在网上很容易地找到这个答案。


请注意,如果在 checkoutadd 之间执行 git status,文件仍显示为“都已修改”。
您知道是否有办法对所有处于冲突状态的文件执行此操作?如果是这样,那将是您答案的一个很好的扩展。
我这样做:git reset --hard 然后 git pull [remote server name] [branch name] -Xtheirs(撤消合并然后将新内容拉到我的内容之上) - 不确定这是否是您想要的。
D
Dan Dascalescu

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

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

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

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

它是如何工作的? git fetch does git pull but without merge。然后 git reset --hard 使您的工作树与最后一次提交匹配。您对 repo 中文件的所有本地更改都将是 discarded,但新的本地文件将保持不变。


+1 - git fetch && git reset --hard {remote}/{branch} 解决了我的问题。我需要完全放弃自己的更改,转而支持分支的“他们的”状态,但是 git pull -X theirs 阻塞了一些移动/重命名的文件。谢谢!
但是如果我在 git pull 之后回到冲突状态,可能我不应该拉 git,但为什么不呢?
L
Lee Chee Kiam

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

git merge --abort
git pull -X theirs

开门见山。出色的!
对我来说,我使用了 git merge <your-branches> -X theirs
git pull -r origin main -X theirs
S
SridharKritha

VS Code(集成 Git)IDE 用户:

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

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

同样,您可以对其他选项进行操作,例如 Accept All Both、Accept All Current 等,


这似乎只适用于单个文件,但并非所有有冲突的文件。
C
Community

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

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 --ours does not remove files from unmerged files list


C
CodeWizard

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

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

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

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

对于在 windows 上无法访问管道 xargs 的人来说,这是如何翻译的?
它不会完全跳过您的更改吗?甚至那些不处于冲突状态的?
这就是我最终做的。不幸的是,它随后需要 git cherry-pick --continue git commit --allow-empty 命令来提交这些更改,并且似乎没有系统需要该命令,这使得自动化变得很痛苦。我目前正在通过测试 .git/COMMIT_EDITMSG 文件的存在来解决这个问题,但这看起来很老套而且很脆弱,而且我还不相信它总是有效的。
这很好,这意味着如果您手动解决一些问题(并执行 git add),那么您可以通过它批量解决其余问题。 git checkout --ours / git checkout --theirs 也很有用。
C
CervEd

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

假设我们有一个文件 foo,其中包含两个提交/分支/树/任何内容的更改。如果他们引入了冲突以及修改,并且我们想使用 ours 解决冲突 - 那么使用 checkout --ours foo 将丢弃引入冲突的更改以及修改。

使用 SED

使用他们的解决方案:

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

-i 就地修改文件,

/^<<<<<<

/^>>>>>>>>/d 删除剩余的冲突标记

-e 为 SED 指定多个模式

foo 文件

使用我们的解决方案:

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

我制作了一个 script,您可以将其称为 git resolve -o/-t/-b

创建自定义合并工具

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

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

并称之为git mergetool --tool=ours


我开始在 Git 邮件列表上讨论它以寻求可能的解决方案:public-inbox.org/git/…
检出整个文件而不是仅仅解决实际的合并冲突的问题就是为什么我发现所有其他答案都没有帮助,甚至基于问题的措辞是错误的。令人惊讶和不幸的是,在 git 中没有集成工具,而必须使用 sed 来代替。
G
Gordon

我有一个长期运行的 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

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


A
Amos Folarin

来自 https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging 这基本上会进行假合并。它将以两个分支作为父分支记录一个新的合并提交,但它甚至不会查看您正在合并的分支。它只会将合并的结果记录为当前分支中的确切代码。 $ git merge -s ours mundo 由 'ours' 策略进行的合并。 $ git diff HEAD HEAD~ 可以看到我们所在的分支和合并的结果没有区别。这通常很有用,可以基本上诱使 Git 在稍后进行合并时认为分支已经合并。例如,假设您分支了一个发布分支,并且已经完成了一些工作,您希望在某个时候合并回您的主分支。同时,需要将 master 上的一些错误修复移植到您的发布分支中。您可以将错误修复分支合并到发布分支中,也可以将相同的分支合并到您的主分支中(即使修复已经存在),因此当您稍后再次合并发布分支时,错误修复不会发生冲突。

如果我希望 master 反映新主题分支的更改,我发现这种情况很有用。我注意到 -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

现在签出主分支

$ git checkout master

合并主题分支,但这次使用 -Xtheirs 递归策略,这将为您呈现一个主分支,其状态为 topicFoo。

$ git merge -X theirs topicFoo

S
S. Hesam

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

git merge [branch] --strategy-option ours

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

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

git merge [branch] --strategy-option theirs

a
arvidj

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

(defun smerge-keep-mine-all ()
  ""
  (interactive)
  (beginning-of-buffer)
  (while (progn (smerge-next) t)
    (smerge-keep-mine)))

(defun smerge-keep-other-all ()
    ""
  (interactive)
  (beginning-of-buffer)
  (while (progn (smerge-next) t)
    (smerge-keep-other)))

T
Thirsty Six

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

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

git pull -X theirs

git pull origin master

git reset --hard 将销毁所有未提交的更改
S
Shayan Amani

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

fatal: Not possible to fast-forward, aborting.

所以你可能想用快进拉取并接受他们的改变:

$ git pull -X theirs --ff