首先:
git merge origin/remote_branch
建议使用 git merge --no-commit
命令,以确保如果没有合并冲突,Git 不会提交这些更改,否则您的下一步将没有多大意义。请注意,如果 --theirs
提交已更改了一些 pom.xml
文件并且您没有更改它们,或者如果 Git 认为已成功合并了您和他们的更改,则根本不会出现合并冲突。(如果您想在其中一种情况下使用 theirs,那也有点棘手,但是您似乎总是想使用 --ours
版本。)
接下来:
git checkout --ours **/pom.xml pom.xml
这取决于您的shell(可能是或类似的),以您想要的方式展开
**
;您可能希望引用星号,并让Git进行全局扩展。不过这会影响到您的特定情况,而且我不确定Git在合并冲突期间如何处理此问题,因此在执行任何此类操作之前,您需要仔细实验。
This works great except if a pom.xml file has been removed in the local branch. After running command #2 above we get an error:
d:\code>git checkout --ours **/pom.xml pom.xml
error: path 'blah/pom.xml' does not have our version
对于这种情况,如果你想保留已删除的文件,你需要覆盖Git默认的操作,选择在索引和工作树中保留它们的版本。
让我们进入所有这些内容中与Git相关的部分,即索引。请记住,Git的索引是您构建下一个提交的地方。在合并期间,它也是您解决冲突的地方。
合并期间索引中的条目
在正常(非合并)情况下,索引为每个被跟踪的文件都有一个条目。如果文件F在当前(HEAD)提交和工作树中,则索引具有F的条目。最初,此索引条目版本与HEAD版本相匹配。您可以在工作树中修改文件,然后git add
工作树版本以将其复制到索引中以替换HEAD版本;然后下一个git commit
将保存索引版本。
在冲突合并期间,文件F存在冲突,索引会有最多三个条目,而不是通常的一个。这些条目将放置在1、2和3号槽中(0号槽保留用于正常、无冲突的条目)。第1号槽用于合并基础版本。第2号槽用于--ours
,第3号槽用于--theirs
,您可以直接使用这些名称来表示第2和第3号槽,但是第1号槽没有名称。
当发生合并冲突时:
- 我们和他们相对于基础版本修改了同一行或几行代码(这是修改/修改冲突),或者
- 没有基础版本,只有我们和他们(这是创建/创建冲突),或者
- 我们删除了文件,他们更改了某些内容,即使只是文件名(这是删除/修改或删除/重命名冲突),或者
- 他们删除了文件,我们更改了某些内容:这也是修改/删除或重命名/删除冲突,但是交换了伙伴关系。
对于修改/修改冲突,三个插槽都被填充了。对于另外三种类型的冲突,一个插槽为空:合并基础插槽为空(创建/创建),或者
--ours
为空(删除/X),或者
--theirs
为空(X/删除)。
当
--ours
插槽为空时,
git checkout --ours
步骤将失败。当
--ours
插槽非空时,它会成功地将
--ours
版本提取到工作目录中。
Git在任何删除/X或X/删除冲突上的默认操作是保留工作目录中幸存的任一版本。也就是说,如果插槽3(theirs)为空,则工作目录文件与插槽2条目匹配,但如果插槽2(ours)为空,则工作目录文件与插槽3条目匹配。
您可以通过扫描空的“插槽2”并在此情况下使用
git rm
来处理此问题:
git ls-files --stage | fancy-script-or-program
如果你将其编写为Python程序,可以使用
git ls-files -z --stage
使其易于机器解析。你甚至可以完全停止使用
git checkout --ours
,停止依赖shell或Git globbing,并在脚本中编写用于解决
pom.xml
文件的规则。从根本上讲,你可以阅读整个索引,查找基本名称(最终
/
之后的所有内容)与
pom.xml
匹配的文件:
如果存在一个零阶段条目,Git认为它已经正确地解决了文件。请将哈希ID与
HEAD
提交中的哈希ID进行比较,因为Git实际上可能并没有正确地解决文件;在这种情况下,请使用
HEAD
提交中的哈希ID替换索引blob哈希。有关详细信息,请参见
git update-index
文档。您应该能够使用
--cacheinfo
,尽管我没有测试过未合并的索引条目。
否则,存在1、2或3个阶段的条目。如果存在第2阶段条目,请将其用作解决方案,即像上面那样将其提供给
git update-index
。如果没有第2阶段条目,请使用
git update-index
来
删除条目(使用0作为模式,使用任何内容,包括全零哈希,作为哈希;如果模式为0,则哈希无关紧要)。
一旦您完成了所有
pom.xml
路径的操作,任何剩余的非零阶段索引条目都表示合并冲突,您应将其传递回给用户。否则,您可能已经准备好提交。
(快速扫描
http://gitpython.readthedocs.io/en/stable/reference.html#module-git.index.base表明这在GitPython中可以相当容易地完成,但我没有使用它的经验。)
最后的警告:我完全没有Maven的经验,但我知道
pom.xml
文件是控制各种东西的XML文件,而Git合并效果不佳(这对几乎所有XML文件都是正确的)。我并不清楚仅使用“我们”的版本是否正确。
|&
表示将_stderr_和_stdout_都传输到第二个命令。然而,并非所有的shell都支持它。在bash
中,只有4+版本才支持它。对于旧的shell,请使用:git checkout --ours -- path/to/some/dir 2>&1 | gawk '{ print $3 }' | xargs git rm
2>&1
运算符意味着将_syserr_传输到相同的_stdout_,结果相同。 - jfaleirorm
命令运行正常,但是接下来的git checkout --ours path/to/my/file.file
命令给我留下了一个错误:error: pathspec 'path/to/my/file.file' did not match any file(s) known to git
。明确一下,我已经在合并的目标分支中从本地删除了这个文件。编辑:看起来,如果我逐个文件处理,git rm
命令就足够了... 文件现在已经合并/冲突已解决。?? - undefinederror: pathspec...did not match any file(s) known to git
表示 git 在其.git
文件夹中找不到该文件。首先尝试运行git fetch
从远程下载所有本地不存在的更改。请参考这里。除此之外,我不清楚。我无法看到你的终端或你的屏幕上的确切情况和存储库。还要记住,rm
和git rm
不完全相同。我认为git rm file
等同于先运行rm file
,然后运行git add file
,这样会将删除操作暂存起来。在上面的命令中,我使用了git rm
。 - undefinedcheckout --ours
命令,它就会正常工作!”是多余的。再次强调,这只适用于我的情况。也就是说,我相信您的答案很好,但是对于其他人来说,根据您的用例,仅仅运行git rm
命令来删除每个已删除的文件可能已经足够解决冲突。 - undefined