我如何接受来自 "their" 分支的 git 合并冲突,仅针对特定目录?
How do I accept git merge conflicts from "their" branch for only a certain directory?
这是我的情况:git merge master
导致 50 个文件存在合并冲突。我希望其中 45 个被 master
接受并完成,我想 手动解决 剩余 5 个中的冲突。所有 45 个文件都在目录 some/dir
。其他 5 个分散在其他地方。 IF 我只想接受 master 对所有 50 个冲突的更改,我会 运行 这个:
git merge -X theirs master
# OR (same thing):
git merge --strategy-option theirs master
但我不想那样,就像我说的那样。我想要更多这样的东西:
git merge -X theirs master some/dir
以便它自动为 some/dir
中的所有冲突选择“他们的”(主人的)一方,否则让我手动修复冲突。然而,这并不存在。
所以,我的解决方法是:
简短说明:
开始合并,在众多冲突文件中手动修复我需要的几个文件。备份我刚刚修复的所有文件。中止合并。重做与 git merge -X theirs master
的合并以自动接受 master
对所有文件中所有冲突的更改。手动将我的几个手动修复的文件复制回 repo,然后提交它们。
这避免了必须手动修复 50 个文件,当只有 5 个真正需要我注意时,这可能会非常乏味和耗时。
完整、详细的步骤:
开始正常合并:
git merge master
仅手动解决我要在其中执行此操作的 5 个文件中的冲突,并保存每个文件。 然后,将它们复制到外部位置回购的(或至少在被回购忽略的文件夹中)。我现在拥有我手动解析的那 5 个文件的副本。这是实现此目的的一种方法:
mkdir -p temp # create `temp` dir inside the repo.
# Note: if you're not aware, the ".git/info/exclude" file in your repo is
# an **untracked** form of a ".gitignore" file for the repo. We will use
# this file below.
# Add a `/temp/` entry to the ".git/info/exclude" file to keep
# the repo from tracking the /temp/ dir, but withOUT using the
# shared ".gitignore" file since this is my own personal setting
# not everyone else on the team necessarily wants.
echo -e "\n# don't track this temporary folder for my arbitrary use\n/temp/" \
>> .git/info/exclude
# Now manually make copies of your 5 files you just resolved conflicts in:
cp some/dir/file1.cpp temp
cp some/dir/file2.cpp temp
cp some/dir/file3.cpp temp
cp some/dir/file4.cpp temp
cp some/dir/file5.cpp temp
git merge --abort
中止合并,然后 git merge -X theirs master
重做合并,除了这次自动接受 master 对所有 50 个文件的所有更改(即:对于所有冲突)。
现在,手动将我手动解析的备份副本从上面复制回各自文件顶部的存储库中:
cp temp/file1.cpp some/dir
cp temp/file2.cpp some/dir
cp temp/file3.cpp some/dir
cp temp/file4.cpp some/dir
cp temp/file5.cpp some/dir
最后,执行 git add -A
和 git commit --amend
将它们修改为合并提交,瞧!我有 45 个文件的自动解析和 5 个文件的手动解析。
有没有更好的方法?
我认为这种方法非常有效,但我愿意学习替代方法,尤其是如果它们更快或更容易。
更新:. The 实际上不正确,并产生错误 在某些非常重要的情况下的行为,尽管投票最多。
相关,但不重复:
- Simple tool to 'accept theirs' or 'accept mine' on a whole file using git
解决冲突时可以直接从其他分支checkout文件
所以在完成 git merge
并解决您需要修复的文件的冲突后。
执行git checkout <branch you're merging> -- some/dir
这会将文件从其他分支移出,仅包含这些更改。我相信这也会让他们做好准备。
如果 ours
分支有变化,您可以只列出 --
之后的文件,而不是只检查整个目录。
我认为@Schleis 的回答很好。如果你的 repo squash-merges 无论如何,另一种选择是......在你开始合并之前,只需执行:
git checkout gabriel.staples/MyBranch
git checkout develop path/You/Want/To/Accept/Everything
git add path/You/Want/To/Accept/Everything
git commit -m "Partially merge develop at SHA XXXXX (squash-style)"
git merge develop
<resolve conflicts>
git add path/To/Your/Hand/Resolved/Files
git merge --continue
如果你真的想要,你也可以使上面更接近真正的合并(给它一个parent)使用:
git commit-tree aboveMergeSHA^{tree} -p `git merge-base develop pseudoMergeSHA` -p develop -m "Merge develop at SHA XXXXX"
但在这一点上,我认为您不妨使用@Schleis 的回答。我不喜欢在不需要时手动弄乱 parents...
在 6 个月前投票并标记为正确 之后,我今天意识到在一个非常大且非常拙劣的 merge
之后,这个答案是错误的。假设您这样做了,用来自 master
:
的最新更改更新您的 feature_branch
git checkout feature_branch
git merge master
# conflicts result...
...还有很多冲突。您看到其中 25 个在 some/dir
中,并且您希望保留来自 feature_branch
的所有冲突更改,因此您执行以下 3 个命令中的任何一个(在本例中都是相同的):
git checkout -- some/dir
# OR
git checkout HEAD -- some/dir
# OR
git checkout feature_branch -- some/dir
好吧,你搞砸了! master
(git merge
的 --theirs
方)还在 some/dir
中添加了一些更改和新文件,其中许多与您的 feature_branch
更改零冲突( git merge
的 --ours
端),以及所有你 想要的 (这是将最新的 master
合并到你的 feature_branch
!) 但现在它们 都消失了 因为你只是用 feature_branch
中的 some/dir
覆盖了它们。这根本不是我们想要的!
所以,这是正确答案:
# RIGHT ANSWER
# NB: you must be **in the middle of resolving conflicts in a `git merge`**
# in order for this to have the behavior I describe here.
# **Keep conflicting changes** for all conflicts within files inside
# some/dir, from the "--ours" (`feature_branch` in this case) side.
# This does NOT delete files added by the `master` (`--theirs`) side which
# have **no conflicts** with your `feature_branch` (`--ours`) side.
git checkout --ours -- some/dir
git add some/dir
git merge --continue
再说一次,这不是一回事:
# WRONG ANSWER
# **Overwrite this entire `some/dir` directory** with everything from
# the `feature_branch` (`--ours`) side.
# This DOES delete files added by the `master` (`--theirs`) side which
# have **no conflicts** with your `feature_branch` (`--ours`) side,
# which is NOT what we want.
git checkout feature_branch -- some/dir
git add some/dir
git merge --continue
因此,这是完整上下文中的正确答案:
# merge latest master into feature_branch to get those upstream changes
# from other people into your feature_branch
git fetch origin master:master
git checkout feature_branch
git merge master
# conflicts result here...
# Keep all changes from `feature_branch` for conflicts in some/dir
git checkout --ours -- some/dir
# OR, keep all changes from `master` for conflicts in some/dir
git checkout --theirs -- some/dir
git add some/dir
git merge --continue
完成!
有关详细信息和清晰度,请在此处查看我的回答:Who is "us" and who is "them" according to Git?。 that answer 的“WARNING WARNING WARNING”部分对此进行了介绍,尽管 this answer 是一个更详尽的示例,并且更好地展示了问题。
这是我的情况:git merge master
导致 50 个文件存在合并冲突。我希望其中 45 个被 master
接受并完成,我想 手动解决 剩余 5 个中的冲突。所有 45 个文件都在目录 some/dir
。其他 5 个分散在其他地方。 IF 我只想接受 master 对所有 50 个冲突的更改,我会 运行 这个:
git merge -X theirs master
# OR (same thing):
git merge --strategy-option theirs master
但我不想那样,就像我说的那样。我想要更多这样的东西:
git merge -X theirs master some/dir
以便它自动为 some/dir
中的所有冲突选择“他们的”(主人的)一方,否则让我手动修复冲突。然而,这并不存在。
所以,我的解决方法是:
简短说明:
开始合并,在众多冲突文件中手动修复我需要的几个文件。备份我刚刚修复的所有文件。中止合并。重做与 git merge -X theirs master
的合并以自动接受 master
对所有文件中所有冲突的更改。手动将我的几个手动修复的文件复制回 repo,然后提交它们。
这避免了必须手动修复 50 个文件,当只有 5 个真正需要我注意时,这可能会非常乏味和耗时。
完整、详细的步骤:
开始正常合并:
git merge master
仅手动解决我要在其中执行此操作的 5 个文件中的冲突,并保存每个文件。 然后,将它们复制到外部位置回购的(或至少在被回购忽略的文件夹中)。我现在拥有我手动解析的那 5 个文件的副本。这是实现此目的的一种方法:
mkdir -p temp # create `temp` dir inside the repo. # Note: if you're not aware, the ".git/info/exclude" file in your repo is # an **untracked** form of a ".gitignore" file for the repo. We will use # this file below. # Add a `/temp/` entry to the ".git/info/exclude" file to keep # the repo from tracking the /temp/ dir, but withOUT using the # shared ".gitignore" file since this is my own personal setting # not everyone else on the team necessarily wants. echo -e "\n# don't track this temporary folder for my arbitrary use\n/temp/" \ >> .git/info/exclude # Now manually make copies of your 5 files you just resolved conflicts in: cp some/dir/file1.cpp temp cp some/dir/file2.cpp temp cp some/dir/file3.cpp temp cp some/dir/file4.cpp temp cp some/dir/file5.cpp temp
git merge --abort
中止合并,然后git merge -X theirs master
重做合并,除了这次自动接受 master 对所有 50 个文件的所有更改(即:对于所有冲突)。现在,手动将我手动解析的备份副本从上面复制回各自文件顶部的存储库中:
cp temp/file1.cpp some/dir cp temp/file2.cpp some/dir cp temp/file3.cpp some/dir cp temp/file4.cpp some/dir cp temp/file5.cpp some/dir
最后,执行
git add -A
和git commit --amend
将它们修改为合并提交,瞧!我有 45 个文件的自动解析和 5 个文件的手动解析。
有没有更好的方法?
我认为这种方法非常有效,但我愿意学习替代方法,尤其是如果它们更快或更容易。
更新:
相关,但不重复:
- Simple tool to 'accept theirs' or 'accept mine' on a whole file using git
解决冲突时可以直接从其他分支checkout文件
所以在完成 git merge
并解决您需要修复的文件的冲突后。
执行git checkout <branch you're merging> -- some/dir
这会将文件从其他分支移出,仅包含这些更改。我相信这也会让他们做好准备。
如果 ours
分支有变化,您可以只列出 --
之后的文件,而不是只检查整个目录。
我认为@Schleis 的回答很好。如果你的 repo squash-merges 无论如何,另一种选择是......在你开始合并之前,只需执行:
git checkout gabriel.staples/MyBranch
git checkout develop path/You/Want/To/Accept/Everything
git add path/You/Want/To/Accept/Everything
git commit -m "Partially merge develop at SHA XXXXX (squash-style)"
git merge develop
<resolve conflicts>
git add path/To/Your/Hand/Resolved/Files
git merge --continue
如果你真的想要,你也可以使上面更接近真正的合并(给它一个parent)使用:
git commit-tree aboveMergeSHA^{tree} -p `git merge-base develop pseudoMergeSHA` -p develop -m "Merge develop at SHA XXXXX"
但在这一点上,我认为您不妨使用@Schleis 的回答。我不喜欢在不需要时手动弄乱 parents...
在 6 个月前投票并标记为正确 merge
之后,这个答案是错误的。假设您这样做了,用来自 master
:
feature_branch
git checkout feature_branch
git merge master
# conflicts result...
...还有很多冲突。您看到其中 25 个在 some/dir
中,并且您希望保留来自 feature_branch
的所有冲突更改,因此您执行以下 3 个命令中的任何一个(在本例中都是相同的):
git checkout -- some/dir
# OR
git checkout HEAD -- some/dir
# OR
git checkout feature_branch -- some/dir
好吧,你搞砸了! master
(git merge
的 --theirs
方)还在 some/dir
中添加了一些更改和新文件,其中许多与您的 feature_branch
更改零冲突( git merge
的 --ours
端),以及所有你 想要的 (这是将最新的 master
合并到你的 feature_branch
!) 但现在它们 都消失了 因为你只是用 feature_branch
中的 some/dir
覆盖了它们。这根本不是我们想要的!
所以,这是正确答案:
# RIGHT ANSWER
# NB: you must be **in the middle of resolving conflicts in a `git merge`**
# in order for this to have the behavior I describe here.
# **Keep conflicting changes** for all conflicts within files inside
# some/dir, from the "--ours" (`feature_branch` in this case) side.
# This does NOT delete files added by the `master` (`--theirs`) side which
# have **no conflicts** with your `feature_branch` (`--ours`) side.
git checkout --ours -- some/dir
git add some/dir
git merge --continue
再说一次,这不是一回事:
# WRONG ANSWER
# **Overwrite this entire `some/dir` directory** with everything from
# the `feature_branch` (`--ours`) side.
# This DOES delete files added by the `master` (`--theirs`) side which
# have **no conflicts** with your `feature_branch` (`--ours`) side,
# which is NOT what we want.
git checkout feature_branch -- some/dir
git add some/dir
git merge --continue
因此,这是完整上下文中的正确答案:
# merge latest master into feature_branch to get those upstream changes
# from other people into your feature_branch
git fetch origin master:master
git checkout feature_branch
git merge master
# conflicts result here...
# Keep all changes from `feature_branch` for conflicts in some/dir
git checkout --ours -- some/dir
# OR, keep all changes from `master` for conflicts in some/dir
git checkout --theirs -- some/dir
git add some/dir
git merge --continue
完成!
有关详细信息和清晰度,请在此处查看我的回答:Who is "us" and who is "them" according to Git?。 that answer 的“WARNING WARNING WARNING”部分对此进行了介绍,尽管 this answer 是一个更详尽的示例,并且更好地展示了问题。