【问题标题】:How do I accept git merge conflicts from "their" branch for only a certain directory?如何仅针对某个目录接受来自“他们的”分支的 git 合并冲突?
【发布时间】:2020-12-16 18:51:11
【问题描述】:

这是我的情况: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

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

git merge -X theirs master some/dir

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

所以,我的解决方法是:

简短说明:

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

这避免了必须手动修复 50 个文件,当我真正需要注意的只有 5 个文件时,这可能会非常乏味和耗时。

完整的详细步骤:

  1. 开始正常的合并:

     git merge master
    
  2. 手动解决我想要在其中执行此操作的 5 个文件中的冲突,并保存每个文件。 然后,将它们复制到 repo 之外的位置(或至少在文件夹中回购忽略了这一点)。我现在有我手动解决的那 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
    
  3. 执行git merge --abort 中止合并,然后执行git merge -X theirs master 重新执行合并,但这次自动接受所有50 个文件的所有master 更改(即:对于所有冲突)。

  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
    
  5. 最后,执行git add -Agit commit --amend 将它们修改为合并提交,瞧!我对 45 个文件进行了自动解析,对 5 个文件进行了手动解析。

有没有更好的方法?

我认为这种方法效果很好,也很有效,但我愿意学习替代方法,尤其是如果它们更快或更容易的话。

相关,但重复:

  1. Merging two branches, how do I accept one branch for all conflicts
  2. Simple tool to 'accept theirs' or 'accept mine' on a whole file using git

【问题讨论】:

  • 我想你可能正在寻找this answer,从例如获取剩余的未合并文件。 git ls-files -u,在每个节点上运行脚本解析器,添加结果。

标签: git merge git-merge


【解决方案1】:

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

所以在执行git merge 并解决您需要修复的文件的冲突之后。

执行git checkout <branch you're merging> -- some/dir 这将仅将这些更改从另一个分支移出。我相信这也会让他们准备好提交。

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

【讨论】:

  • 另请参阅我的答案的合并冲突解决示例部分:Who is “us” and who is “them” according to Git?
  • 顺便说一句,这很好用。我刚刚测试过了!我从来不知道你可以将 some/dir 这样的目录传递给 git。我一直认为您必须单独指定文件。
  • @GabrielStaples 对目录的一个警告是它们不能为空。 Git 只跟踪文件,所以空目录会导致问题。
  • Schleis,不幸的是,事实证明你的答案毕竟不正确。我现在已经详细说明了问题和正确的解决方案in my new answer here
【解决方案2】:

我认为@Schleis 的回答很好。如果您的 repo squash-merge 无论如何,另一种选择是......在您开始合并之前,只需执行以下操作:

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

如果你真的想要,你也可以使用以下方法使上述更接近真正的合并(给它一个父级):

git commit-tree aboveMergeSHA^{tree} -p `git merge-base develop pseudoMergeSHA` -p develop -m "Merge develop at SHA XXXXX"

但在这一点上,我认为您不妨使用@Schleis 的回答。我不喜欢在不需要的时候手动惹父母……

【讨论】:

    【解决方案3】:

    在 6 个月前投票并标记为正确的 this answer 之后,我今天意识到在一个非常大且非常拙劣的 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 还在 some/dir 中添加了一些更改和新文件,其中许多与您的 feature_branch 更改零冲突,而所有这些都是您想要的(这就是合并的重点最新的master 到你的feature_branch!)但现在它们都消失了,因为你只是用来自feature_branchsome/dir 覆盖了它们。这根本不是我们想要的!

    所以,这里是正确的答案:

    # RIGHT ANSWER
    
    # Keep only conflicting changes for all conflicts within files inside
    # some/dir, from the "--ours" (`feature_branch` in this case) side.
    git checkout --ours -- some/dir
    

    再一次,这和这个不一样:

    # WRONG ANSWER
    
    # Overwrite this entire directory 
    git checkout feature_branch -- some/dir
    

    所以,这里是完整上下文的正确答案:

    # 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 是一个更彻底的例子,并且更好地显示了问题。

    【讨论】:

      猜你喜欢
      • 2014-04-27
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 2012-03-02
      • 1970-01-01
      • 2018-03-01
      相关资源
      最近更新 更多