此问题使用Git 2.7.0.windows.1
,因此某些git命令可能已过时。
如果我的git merge
命令没有检测到重命名的文件,我怎么能告诉git手动合并两个应该是单个文件的文件中的更改,而不启动合并并使用较低的重命名阈值?
复制步骤:
git init
echo "//Hello world!" > hw.h
git add . && git commit -m "Initial commit"
git checkout -b someBranch
mv hw.h hw.hpp
echo "//Foobar" > hw.hpp
git add . && git commit -m "Change hw to HPP & change content"
git checkout master
echo "//Boofar" > hw.h
git add . && git commit -m "Change content of hw"
git merge -X rename-threshold=100% someBranch
您将遇到合并冲突,但没有冲突的块。也就是说,你应该得到的唯一冲突/错误是:
CONFLICT (modify/delete): hw.h deleted in branchB and modified in HEAD. Version HEAD of hw.h left in tree.
Automatic merge failed; fix conflicts and then commit the result.
git status --porcelain
将显示:
UD hw.h
A hw.hpp
通常,在合并时,将检测重命名的阈值设置得足够低以检测重命名是理想的。例如Some people recommend 5%。在我的情况下,我正在进行大规模合并(> 1000个文件和大约9m LOC),我不得不将重命名阈值提高到足以避免任何误报&#34 ;;几乎百分之一低,我得到了大量错误检测到的重命名(我知道,重复的代码很糟糕)。在我最后使用的价值中,我只获得了一小部分错过的重命名,这似乎是一个更好的选择。
TL;降低重命名阈值的DR不适合我;如果不开始合并,我怎么能告诉git将hw.h
和hw.hpp
视为单个文件(有冲突),而不是如上所示的两个文件?
答案 0 :(得分:3)
这方面的工具有点笨拙,但他们 那里。
您需要确保合并本身在提交之前停止。在你的情况下,这会自动发生。对于棘手的合并,Git认为它正确地执行但不是,你会添加--no-commit
,但这会影响接下来的几个步骤。我们暂时忽略这个问题。
接下来,您需要获取相关文件的所有三个版本。由于Git因冲突而停止,我们处于良好状态:这三个版本都可以通过索引访问。请记住,我们关注的三个版本是合并基础,--ours
和--theirs
。
如果Git 正确检测到重命名,则所有三个版本都将位于单名称下的索引中。既然没有,它们就不是:我们需要两个名字。 (使用“Git认为它正确合并”的情况下,文件的合并基本版本根本不在索引中,我们必须以其他方式检索它。)在这种情况下,这两个名称是{{ 1}}和hw.h
,现在我们这样做:
hw.hpp
(重命名不是绝对必要的,只是为了帮助保持一切,并且很好地说明。)
现在我们要将一个文件与$ git show :1:hw.h > hw.h.base # extract base version
$ git show :2:hw.h > hw.h # extract ours
$ mv hw.hpp hw.h.theirs # move theirs into place
合并:
git merge-file
这使用您配置的$ git merge-file hw.h hw.h.base hw.h.theirs
,以便合并文件中的内容看起来正如您所期望的那样,但冲突行上的标签略有不同。我设置了merge.conflictStyle
,所以我得到了:
diff3
您现在可以照常解决此问题,$ cat hw.h
<<<<<<< hw.h
//Boofar
||||||| hw.h.base
//Hello world!
=======
//Foobar
>>>>>>> hw.h.theirs
额外rm
和.base
个文件,.theirs
最终结果git add
和{{1} }}。 (这取决于你何时到git rm --cached hw.hpp
:在提交之前的任何时间点这样做是安全的,但是一旦完成,你就不能再从索引获得“他们的”了;参见下文)。
请注意,git commit
和git rm --cached hw.hpp
也可以使用“我们的”和“他们的”版本。要获得没有索引的基本版本,我们必须运行git show HEAD:path
来查找其哈希ID(然后假设有一个合并基础以及 1 ),并且{{1 }}。如果Git认为它已正确完成合并,那么我们必须这样做。
另请注意,如果您真的想要 - 我想这只有在您想要使用其他工具时才会出现这种情况,这需要它 - 您可以使用git show MERGE_HEAD:path
来改变周围的条目在索引中,将git merge-base HEAD MERGE_HEAD
移动到git show <hash>:path
的第3行,以便 显示为“他们的”,并在git update-index
中以这种方式显示。对于这个特例:
hw.hpp
哈希来自hw.h
,是git status
的哈希值。 (您需要第二步删除 $ printf '100644 bbda177a6ecfe285153467ff8fd332de5ecfb2f8 3\thw.h' |
git update-index --index-info
索引条目。)
1 使用git ls-files --stage
查找所有合并基础。如果有多个,您可以任意选择一个(这是hw.hpp
所做的),或者尝试将所有合并基础合并到虚拟合并库中。要合并两个合并库,您会找到他们自己的合并库,并使用该合并库合并两个库,就像它们是分支提示一样。根据需要进行递归和迭代 - 这是Git对默认hw.hpp
策略所做的事情 - 直到您拥有该文件的单个合并基本版本。