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


207

经过一阵子我正在重新扎根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

通常,我只是打开文件或合并工具,然后手动接受所有“其”或“我的”更改。但是,我怀疑我缺少方便的git命令。

另外,请注意,当我看到哪些文件遇到冲突以及可能是什么冲突时,我将只能为每个文件选择合并策略。


@AbeVoelker我认为这不能解决我的问题。我想为特定文件选择合并策略。另外,请注意,当我处于基准状态时,我只会知道要使用哪种合并策略,并查看哪些文件发生了冲突以及哪些冲突。
史蒂芬·韦克斯勒

我对这个问题进行了更一般的编辑:stackoverflow.com/questions/278081/…。也许我们可以作为一个重复的问题来结束这个问题?这样合适吗

@TheShadow在我看来,这很合理。
史蒂芬·韦克斯勒

我不确定将另一个问题的标题更改为我所做的操作是否合适,因为我删除了解决二进制文件的部分。我将另一个问题恢复到以前的状态,因此当前问题仍然可以增加价值。

Answers:


251

对于收到的每个冲突文件,您可以指定

git checkout --ours -- <paths>
# or
git checkout --theirs -- <paths>

来自git checkout文档

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

--ours
--theirs
从索引中检出路径时,请检出阶段#2(ours)或#3(theirs)中的未合并路径。

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


9
是否可以接受所有未使用的文件的文件?
aslakjo 2013年

41
@aslakjo git rebase -s recursive -X <ours/theirs>git merge -s recursive -X <ours/theirs>。请记住,为进行基础调整,“我们的”和“他们的”与合并过程中的相反。您可能也可以只使用文件/ shell全局文件,例如git checkout --theirs -- *.txt

2
非常感谢@ Cupcake,ours/theirsrebase 的意外逆转让我发疯了!!(现在,我考虑重新设置的实际工作原理是有道理的,但一点都不直观。)
Dan Lenski 2016年

2
通常,@ DanLenski变基只是人们最初了解的一个非常棘手的工具,但是一旦您了解了它的工作原理,就可以使用它来做各种真正强大的事情。

1
@VincentSels实际上,您需要屏蔽*字符,否则,shell会尝试将其扩展。因此,根据您的情况,您便git checkout --outs -- "**/*.csproj"可以做到。例如,也是如此git lfs track "*.jpg"。如果您的CWD中有一些jpg文件,但没有引号,则只会跟踪这些文件。
eFloh '18

117

即使回答了这个问题,也提供了一个示例,说明在git rebase vs merge情况下“他们的”和“我们的”是什么意思。看到这个链接


theirsrebase的情况下,Git Rebase实际上是当前分支。因此,以下命令实际上是在远程分支上接受您当前的分支更改。

# see current branch
$ git branch
... 
* branch-a
# rebase preferring current branch changes during conflicts
$ git rebase -X theirs branch-b

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

# assuming branch-a is our current version
$ git merge -X ours branch-b  # <- ours: branch-a, theirs: branch-b

2
好吧,这是一个很重要的区别!感谢您的澄清。
动词

26

请注意,通过选择或版本,这git checkout --ours|--theirs完全覆盖文件,这可能是或可能不是您要执行的操作(如果您有来自另一端的任何无冲突的更改,它们将会丢失)。theirsours

相反,如果您要对文件执行三向合并,并且仅使用来解决有冲突的块--ours|--theirs,同时双方没有冲突的块保留在适当的位置,则您可能要诉诸于git merge-file; 查看此答案的详细信息。


1
关于将丢失的“无冲突的更改”-这仅指的是特定行中无冲突的更改的文件,而在同一文件中的其他文件,或在历史记录中所有文件的所有更改?
ktamlyn

2
@ktamlyn用“无冲突的更改”来表示同一文件中的更改。例如,有两个改变后的厚片(份)example.txtours版本,一个是相冲突(在也改变theirs修改),另一种是不冲突。如果这样做git checkout --theirs example.txt,它将仅在theirs修订时盲目读取整个文件,并且diff的非冲突部分将丢失。
jakub.g

1
谢谢!这对我来说是必要的澄清,即使在这种情况下“在同一文件中进行更改”最有意义。
ktamlyn

好的,尽管它并没有真正给出答案,但是应该指出其他建议的解决方案中的重要问题。
tomasyany

1
如果要返回到原始冲突文件,则可以运行git checkout --merge <path>
安德鲁·基顿
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.