我正在执行git merge,其中许多文件以相同的方式在合并的两个分支中移动。令我惊讶的是,对于大约10个文件,git无法在我合并的分支中找到该文件的版本。
即。文件在/path/file.txt中启动。在分支1文件中修改,然后移动到/path/newpath/file.txt。在分支2中,文件被移动到相同的路径/path/newpath/file.txt。当我合并时,我希望git能够处理这个问题。但是,它将此显示为合并冲突,表示文件已从分支1中删除。我有三个问题:
我可以通过我的git索引的手动或脚本更新来使这个合并工作,告诉git另一个分支中文件的对象哈希。根据另一个SO问题的脚本,它看起来像这样:
FILE_PATH = “路径/到/ file.txt的”
git update-index --index-info<< EOI 000000 0000000000000000000000000000000000000000 0 $ FILE_PATH 100644电子邮件向我们提供电子邮件 100644 0ddb2a448cb9cca97834df78ae00e213ecd9dd71 3 $ FILE_PATH EOI
如果我这样做,我还需要告诉git有关共同的祖先对象吗?即使用第2阶段和第3阶段的记录,还是使用update-index为第1阶段输入一个条目?我感到困惑的原因是因为在这个特定的情况下,共同的祖先将有两个其他版本的路径不同,所以即使我要更新索引以包含它,如何告诉git这是祖先!?如果文件路径不同,那么将第1阶段条目与第2阶段和第3阶段条目联系起来会是什么?
答案 0 :(得分:1)
索引保存您想要提交的内容,因此索引中的路径应该是合并提交中的任何内容。但是,这里有多条路径,请参阅下面#3的答案。
按顺序回答您的问题:
“当然,具有相同路径和名称的文件应被视为合并候选”:不一定,因为重命名检测。
Git通过识别合并基础(实际提交,或者在某些极少数情况下使用“递归合并”技巧,通过执行另一次合并进行虚拟提交)开始合并过程,然后区分合并基础 - 整个树 - 针对有问题的两个提交(HEAD
,运行git merge
时所在的提交/分支,以及MERGE_HEAD
,您要求合并的提交)。这会产生两个独立的差异,每个差异都会进行单独的重命名检测。
在这种特殊情况下,path_a
在两个分支中都重命名为path_b
,但实际上只检测到一个重命名。 (如果未检测到重命名,则表示存在“创建/创建冲突”,其中git认为path_b
是在两个分支中独立创建的。如果两者相同已经检测到重命名,git只会合并“从基础path_a
到path_b
和HEAD
MERGE_HEAD
。所以我们可以得出结论,git只有一半成功了。)
由于git没有注意到两个差异之一中的path_b
实际上是从path_a
重命名的,所以它决定在那个差异中你只是删除了path_a
并写了一个完全不同的path_b
。它无法合并任何更改,因为path_b
中的HEAD
与path_b
中的MERGE_HEAD
无关。
您链接的索引更新问题显示了如何告诉git,不,实际上两个path_b
的 都是相关的,并且合并基础版本只是命名为{{1在这两种情况下。然后最后的“git checkout -m”创建适当的合并版本(可能有合并冲突)。
目前,path_a
选项就是全部。按照您链接的问题中的链接,可以获得该脚本,告诉git“事后事件”,因为它错过了任何重命名。
这是我需要进行一些实验的地方。索引条目 告诉git共同祖先的SHA-1,它位于“索引槽1”中。在某种意义上,与它一起使用的路径完全无关:要进行合并,git只需要文件内容(对于所有三个版本:base aka stage 1,HEAD aka stage 2,and MERGE_HEAD又名第3阶段。看起来很可能,无论是基于索引格式还是脚本(https://gist.github.com/tvogel/894374),你需要的路径不是原始路径,而是新提交路径 - 但我不知道肯定不知道。