如何仅接受来自“他们的”分支的某个目录的 git 合并冲突?

Gab*_*les 6 git merge git-merge

这是我的情况:git merge master导致 50 个文件存在合并冲突。我希望其中 45 个文件被接受master并完成,并且我想手动解决其余 5 个文件中的冲突。所有 45 个文件都在目录 中some/dir。其余5人分散在其他地方。如果我只想接受 master 对所有 50 个冲突的更改,我会运行以下命令:

git merge -X theirs master
# OR (same thing):
git merge --strategy-option theirs master
Run Code Online (Sandbox Code Playgroud)

但我不想那样,就像我说的。我想要更多这样的东西:

git merge -X theirs master some/dir
Run Code Online (Sandbox Code Playgroud)

这样它会自动为 中的所有冲突选择“他们的”(主人)一方some/dir,但否则让我手动修复冲突。然而,这并不存在。

所以,我的解决方法是这样的:

简短的介绍:

开始合并,在众多冲突文件中手动修复我需要的几个文件。备份我刚刚修复的所有文件。中止合并。重做合并,git merge -X theirs master以自动接受master所有文件中所有冲突的更改。手动将我的几个手动修复的文件复制回存储库,然后提交它们。

这样可以避免手动修复 50 个文件,而当只有 5 个文件真正需要我注意时,这可能会非常乏味且耗时。

完整、详细的步骤:

  1. 开始正常合并:

     git merge master
    
    Run Code Online (Sandbox Code Playgroud)
  2. 手动解决我想要执行此操作的 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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 中止git merge --abort合并,然后git merge -X theirs master重做合并,除了这次自动接受所有 50 个文件的所有主更改(即:所有冲突)。

  4. 现在,手动将上面手动解析的备份副本复制回存储库中各自文件的顶部:

     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
    
    Run Code Online (Sandbox Code Playgroud)
  5. 最后,将git add -A它们git commit --amend修改为合并提交,瞧!我对 45 个文件进行了相当于自动解析,对 5 个文件进行了手动解析。

有没有更好的办法?

我认为这种方法效果很好并且非常有效,但我愿意学习替代方法,特别是如果它们更快或更容易的话。

更新这就是答案目前获得最多支持的答案实际上是正确的,并且在某些非常重要的情况下会产生错误的行为,尽管它是获得最多支持的答案。

相关但重复:

  1. 合并两个分支,如何接受一个分支来解决所有冲突
  2. 使用 git 在整个文件上“接受他们的”或“接受我的”的简单工具

Sch*_*eis 7

解决冲突时可以直接从其他分支检出文件。

因此,在完成git merge并解决需要修复的文件的冲突之后。

执行git checkout <branch you're merging> -- some/dir此操作会将仅包含这些更改的文件从其他分支移过来。我相信这也将使他们做好承诺的准备。

如果分支有更改ours,您可以只在 后面列出文件,--而不是仅仅检查整个目录。


Gab*_*les 4

在六个月前投票并标记正确这个答案merge之后,今天在一个非常大且非常糟糕的地方需要这个答案之后我意识到这个答案是错误的。假设您这样做是为了feature_branch使用以下最新更改来更新您的master

git checkout feature_branch
git merge master
# conflicts result...
Run Code Online (Sandbox Code Playgroud)

……还有很多冲突。您看到其中有 25 个位于 内部some/dir,并且您希望保留 中的所有冲突更改feature_branch,因此您执行以下 3 个命令中的任何一个(在本例中都是相同的操作):

git checkout -- some/dir
# OR
git checkout HEAD -- some/dir
# OR
git checkout feature_branch -- some/dir
Run Code Online (Sandbox Code Playgroud)

好吧,你刚刚搞砸了!master( 的--theirs一侧git merge)还添加了一些更改和新文件some/dir,其中许多与您的feature_branch更改( 的--ours一侧) 零冲突,以及您想要的git merge所有内容(这就是将最新的内容合并到您的!)但是现在它们都消失了,因为你刚刚用你的from覆盖了它们。这根本不是我们想要的!masterfeature_branchsome/dirfeature_branch

所以,这是正确的答案:

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

再说一次,这和这个不是一回事:

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

因此,这是完整上下文中的正确答案:

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

完毕!

有关详细信息和清晰度,请参阅我的回答:根据 Git,谁是“我们”,谁是“他们”?该答案的“警告警告警告”部分涵盖了这一点,尽管该答案是更彻底的示例,并且更好地显示了问题。

  • @onlinespending,看看你的评论并对我的答案投了反对票,我认为你误解了我的问题和我的答案。我的答案其实是正确的答案,而目前点赞最多的答案其实是错误的。我的问题是:_我如何接受来自“他们的”分支的 git merge 冲突,仅针对某个目录?_-意思是:合并所有内容_除了_某个目录,对此我只接受一侧或另一侧。我的答案准确地表明了这一点:合并除“some/dir”内容之外的所有内容,对于该目录,我们只接受一侧或另一侧(“--ours”或“--theirs”)。 (2认同)