当我们合并时,我们保留Maven pom.xml文件的本地版本:
git merge origin/remote_branch
git checkout --ours **/pom.xml pom.xml
git add **/pom.xml pom.xml
git commit -m "Merge"
除非在本地分支中删除了pom.xml文件,否则这很有效。在运行上面的命令#2后,我们得到一个错误:
d:\code>git checkout --ours **/pom.xml pom.xml
error: path 'blah/pom.xml' does not have our version
...并且在此错误之后,下一个命令#3 git add **/pom.xml pom.xml
有效地添加了远程pom.xml文件 - 这正是我们不想要的。
我们如何更新我们的脚本来处理这个?
答案 0 :(得分:2)
运行命令error: path 'some/file' does not have our version
后出现错误git checkout --ours **/some_file2.xml some_file2.xml
如何解决
作为人类,您需要执行以下操作。假设您运行了以下代码,as I explain and recommend here:
git checkout --ours -- path/to/some/dir
...它没有用!它什么也没做。相反,它输出这些错误:
<块引用>error: path 'path/to/some/dir/file1.cpp' does not have our version
error: path 'path/to/some/dir/file2.cpp' does not have our version
error: path 'path/to/some/dir/file3.cpp' does not have our version
问题在于这些是our
端的删除文件,因此我们必须从我们的工作树(工作文件系统)中手动git rm
每个文件,以手动强制我们的工作树匹配这些文件的 our
端:
git rm path/to/some/dir/file1.cpp
git rm path/to/some/dir/file2.cpp
git rm path/to/some/dir/file3.cpp
# OR (same thing)
git rm path/to/some/dir/file1.cpp path/to/some/dir/file2.cpp \
path/to/some/dir/file3.cpp
现在,重新运行您的 checkout --ours
命令,它会正常工作!:
git checkout --ours -- path/to/some/dir
有效!完成。
让我们编写上面的内容。毫无疑问,有很多方法可以做到这一点,但这是我能找到的最简单的方法:
# 1. attempt to run `git checkout --ours` the first time,
# collecting any filenames which errored out, if any, and
# `git rm` them all.
git checkout --ours -- path/to/some/dir \
|& gawk '{ print $3 }' | xargs git rm
# 2. Now run it again. If it worked the first time above already,
# no big deal--running it again causes no problems. If it failed
# above though, the above command just ran `git rm` on all those
# failed files, so now this time it will succeed!
git checkout --ours -- path/to/some/dir
完成!当然,您也可以将第一次尝试的输出存储到文件中,并且仅在第一次尝试失败时才运行第二次尝试(意味着输出不是空字符串),但我会留给您.
示例输出:通过 git rm
删除已删除的文件,您将看到以下输出(此处的第一行包含 $
字符后的实际命令):
$ git checkout --ours -- path/to/some/dir |& gawk '{ print $3 }' | xargs git rm
path/to/some/dir/file1.cpp: needs merge
path/to/some/dir/file2.cpp: needs merge
path/to/some/dir/file3.cpp: needs merge
rm 'path/to/some/dir/file1.cpp'
rm 'path/to/some/dir/file2.cpp'
rm 'path/to/some/dir/file3.cpp'
git checkout --ours -- path/to/some/dir |& gawk '{ print $3 }' | xargs git rm
的解释:
git checkout --ours -- path/to/some/dir
接受来自 --ours
方的所有合并冲突(在我的回答中了解更多信息:Who is "us" and who is "them" according to Git?)。|&
管道两者 stderr
输出以及 stdout
输出,因为可能打印的错误消息通过 git 命令输出到 stderr
这就是我们需要通过管道传输的内容。gawk '{ print $3 }'
仅打印每行的第 3 个空格分隔字段,例如,这意味着它捕获 'path/to/some/dir/file1.cpp'
的 error: path 'path/to/some/dir/file1.cpp' does not have our version
部分。| xargs git rm
将所有这些文件通过管道传送到 git rm
以“git 删除”它们。现在您可以添加这些自动修复的文件并继续该过程:
git add path/to/some/dir
git status
# Use the appropriate one of these based on whatever operation
# you were in at the time when the conflicts happened.
git merge --continue
git rebase --continue
git revert --continue
# etc.
git-diffn.sh
"git diff with line numbers" script(我永远不记得 awk 语法,所以我只查看以前已知的示例,包括我自己的示例)。| xargs git rm
:Git rm several files?|&
对 both stdout 和 stderr 进行管道传输:Piping both stdout and stderr in bash?答案 1 :(得分:1)
首先:
git merge origin/remote_branch
应该读取git merge --no-commit
以确保Git在没有合并冲突的情况下不提交这些更改,否则您的后续步骤没有多大意义。请注意,如果--theirs
提交已更改某些pom.xml
文件并且您尚未更改它们,或者Git认为它已成功合并您的更改及其更改,则根本不存在合并冲突。 (如果你想在其中一种情况下使用它们,那也有点棘手,但你似乎总是想要使用--ours
版本。)
下一步:
git checkout --ours **/pom.xml pom.xml
这依赖于你的shell(大概是bash
或类似的)来扩展**
你想要的方式;你可能想引用星号,并让Git做全局扩展。这可能会影响你的特定情况,而且我不确定Git在合并冲突期间如何处理这个问题,所以在你做这样的事情之前,你需要仔细试验。
除非在本地分支中删除了pom.xml文件,否则这很有效。在运行上面的命令#2后,我们得到一个错误:
d:\code>git checkout --ours **/pom.xml pom.xml error: path 'blah/pom.xml' does not have our version
正确:对于这种情况,如果要保留删除的文件,则需要覆盖Git的默认操作,即选择将其版本保留在索引和工作树中。
让我们跳转到所有这一切的Git特定部分, index 。请记住,Git的索引是您构建 next 提交的地方。在合并期间,您也可以解决冲突。
在正常(非合并)情况下,索引为每个跟踪文件都有一个条目。如果文件 F 在当前(HEAD)提交和工作树中,则索引具有 F 的条目。最初,此索引条目版本与HEAD版本匹配。您可以在工作树中修改文件,然后git add
工作树版本将其复制到HEAD版本的索引中;然后下一个git commit
将保存索引版本。
在冲突合并期间,文件 F 发生冲突时,索引 F 的最多三个条目,而不是通常的条目。这些条目位于插槽号1,2和3中。(插槽零保留用于正常的,不冲突的条目。)插槽1用于合并基础版本。插槽2用于--ours
,插槽3用于--theirs
,您可以将这些名称用于2和3,但插槽1没有名称。
合并冲突发生在:
对于修改/修改冲突,将填充所有三个插槽。对于其他三种类型的冲突,一个槽为空:合并基槽为空(创建/创建),或--ours
为空(删除/ X),或--theirs
为空(X /删除)。
当git checkout --ours
广告位为空时,--ours
步骤失败。当--ours
插槽非空时它会成功:它会将--ours
版本提取到工作树中。
Git对任何删除/ X或X /删除冲突的默认操作是在工作树中保留幸存的版本。也就是说,如果它的第3个插槽(他们的)为空,则工作树文件与插槽2条目匹配,但如果它的插槽2(我们的)是空的,工作树文件与插槽3条目匹配。
你可以选择通过扫描空的&#34;插槽2&#34;和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可能没有正确解析文件;在这种情况下,将索引blob哈希替换为HEAD
提交中的一个。有关详细信息,请参阅the git update-index
documentation。您应该能够使用--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文件的最后都是如此)。对我来说,只使用&#34;我们的&#34;但版本是正确的。