为特定文件选择Git合并策略("我们的","我的","他们的")

Ste*_*ler 186 git git-rebase git-merge-conflict

经过一段时间后,我正处于变相的过程中git pull --rebase.我有一些文件有合并冲突.如何接受特定文件的"他们的"更改或"我的"更改?

$ git status
# Not currently on any branch.
# You are currently rebasing.
#   (fix conflicts and then run "git rebase --continue")
#   (use "git rebase --skip" to skip this patch)
#   (use "git rebase --abort" to check out the original branch)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:  CorrectlyMergedFile
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#       both modified: FileWhereIWantToAcceptTheirChanges
#       both modified: FileWhereIWantToAcceptMyChanges
Run Code Online (Sandbox Code Playgroud)

通常我只是打开文件或合并工具并手动接受所有"他们的"或"我的"更改.但是,我怀疑我错过了一个方便的git命令.

另外,请注意,当我看到哪些文件发生冲突时,我只能为每个文件选择合并策略,可能是冲突.

小智 229

对于您获得的每个冲突文件,您可以指定

git checkout --ours -- <paths>
# or
git checkout --theirs -- <paths>
Run Code Online (Sandbox Code Playgroud)

来自git checkout文档

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
检查索引中的路径时,请检查阶段#2(ours)或#3(theirs)是否有未合并路径.

由于先前失败的合并,索引可能包含未合并的条目.默认情况下,如果您尝试从索引中检出此类条目,则结帐操作将失败,并且不会检出任何内容.使用-f将忽略这些未合并的条目.可以使用--ours或从索引中检出合并的特定一侧的内容--theirs.使用时-m,可以放弃对工作树文件所做的更改以重新创建原始冲突的合并结果.

  • @aslakjo`git rebase -s recursive -X <ours/theirs>`或`git merge -s recursive -X <ours/theirs>`.请记住,对于一个rebase,"我们的"和"他们的"与合并期间的相反.你也许可以只使用一个文件/ shell glob,比如`git checkout --theirs - *.txt`. (40认同)
  • 是否可以接受所有留下的文件? (9认同)
  • 非常感谢@Cupcake,我们的/他们的与计划变更的意外逆转使我发疯了!(现在,我考虑重新配置的实际工作方式是有道理的,但一点都不直观。) (2认同)
  • @DanLenski rebase一般来说只是一个非常棘手的工具,人们最初可以理解,但是一旦你理解了它是如何工作的,你就可以用它来做各种非常强大的事情. (2认同)

Abe*_*Abe 99

尽管回答了这个问题,但在git rebase vs merge的情况下,提供一个关于"他们的"和"我们的"意味着什么的例子.看到这个链接

Git Rebase
theirs实际上是rebase案例中的当前分支.因此,下面的命令集实际上是通过远程分支接受当前的分支更改.

# see current branch
$ git branch
... 
* branch-a
# rebase preferring current branch changes during conflicts
$ git rebase -X theirs branch-b
Run Code Online (Sandbox Code Playgroud)

Git的合并
对于合并的意义theirsours反转.因此,要在合并期间获得相同的效果,即保持当前分支change(ours)在远程分支上合并(theirs).

# assuming branch-a is our current version
$ git merge -X ours branch-b  # <- ours: branch-a, theirs: branch-b
Run Code Online (Sandbox Code Playgroud)

  • 我*认为*这真的很有帮助,因为“我们的”与人们的想法 100% 相反。我们的分支是我们要重新建立基础的分支......对吗?正如预料的那样奇怪。 (5认同)
  • @DanRosenstark 将变基视为: 1. 切换到 `branch-b` (这成为我们的) 2. 从 `branch-a` (这成为他们的)第一个(以及随后的下一个)提交运行 `git commit` 3.对每个其他提交重复步骤 2 4. 将 `branch-a` 指向步骤 3 中的最后一个提交。这就是“他们的”和“我们的”的解释方式 (2认同)

jak*_*b.g 24

请注意,git checkout --ours|--theirs完全覆盖这些文件,通过选择两种theirsours版本,这可能是也可能不是你想要做什么(如果你有从另一面来任何非冲突的变化,他们将丢失).

如果你想要对文件执行三向合并,并且只解决冲突的帅哥使用--ours|--theirs,同时保持双方的非冲突帅哥,你可能想诉诸git merge-file; 看到这个答案中的细节.

  • @ktamlyn的“无冲突的更改”是指同一文件中的更改。例如,在我们的版本中,example.txt中有两个已更改的块(部分),一个已发生冲突(在其版本中也进行了更改),另一个未发生冲突。如果您执行`git checkout --theirs example.txt`,它只会盲目地读取`thes'修订版中的整个文件,并且差异的非冲突部分将丢失。 (2认同)

Kay*_*y V 17

从上面的评论中引用@user456814:

git rebase -s recursive -X <ours/theirs>
或者
git merge -s recursive -X <ours/theirs>

请记住,对于变基,“我们的”和“他们的”与合并期间的情况相反

@user456814 早在 2014 年就在对已接受答案的评论中给出了这个有用的答案。我将其作为社区 wiki 在这里呈现,以便更容易查找、评估、更新等,因为评论在这方面是有限的。