[英]git rebase merge conflicts for soft links
我的用例是在历史记录中的特定提交之后插入新的提交。 我有提交的哈希,之后需要插入一个新的提交。
假设3是我要在以下历史记录中的提交2之后插入的新提交。
1 <-- 2 <-- 4 <-- 5 <-- 6
我按照以下步骤在master分支上。
git checkout -b temp <commit 2 hash>
echo "new commit" > test_file.txt
git add test_file.txt
git commit -a -m "Inserting a new commit"
git rebase -Xours temp master
我从提交2创建了分支临时文件,在该分支上进行了提交并进行了重新设置。 希望历史如下所示,
1 <-- 2 <-- 3 <-- 4 <-- 5 <-- 6
如果存在任何文件合并冲突, -Xours
可以正常工作,但是在软链接中无法显示合并冲突。
错误如下所示
Auto-merging apps/abc/ps_abc
CONFLICT (content): Merge conflict in apps/abc/ps_abc
Auto-merging apps/def/ps_def
CONFLICT (content): Merge conflict in apps/def/ps_def
上面的两个路径是git repo外部目录的软链接。 Git diff对他们不起作用。 如何处理这类冲突?
请帮忙。
根据Git的估计,名为P
的符号链接(其中P
表示类似apps/abc/ps_abc
的路径)只是一个名为P
的文件,其类型为“链接”,其内容为二进制。 由于内容是二进制的,因此Git无法对其进行区分。 您可能会认为-Xours
会告诉Git使用“我们的”,但事实并非如此,因为它永远不会落入低级代码中。
解决方案是选择正确的版本(通过任何您喜欢的方式),并确保它在索引中为零阶段版本,然后继续操作(在本例中为git rebase --continue
)。
合并的合并 -the动词形式-is自一个共同的起点结合变化的过程。 在Git中,这个共同的起点是合并基础提交。 Git使用提交图找到合并基础:使用git checkout mybranch
签出一些特定的提交,然后告诉git git merge theirbranch
。 这两个名称标识两个特定的提交。 Git审视了每个承诺背后的历史,以找到两组工作分开的最佳起点。
对于每个路径P
发生在所有三个提交,Git建立的索引/舞台区进入P
与所有三个文件,使用每个条目中插槽P
在认为尚未合并的文件索引。 基本版本进入插槽1。同一文件的版本进入插槽2,其同一文件的版本进入插槽3。通常,在满足以下所有条件的情况下 ,将发生合并冲突:
P
更改了文件。 P
更改了文件。 对于文本 (非二进制)文件,Git首先观察前三个条件(该文件在所有三个版本中都存在,但在两侧都有更改),并有效地从底部到左侧以及从底部运行git diff
在右边。 然后,Git可以逐行查看这些更改, 并将更改组合为单个常见更改。
如果此过程失败,则Git通常会声明合并冲突并停止。 这将在索引中保留暂存插槽1中文件P
的合并基础版本,暂存插槽2中我们的版本以及暂存插槽3中它们的版本。然后,您可以根据需要合并这三个文件-也许使用显示冲突的工作树版本,或者使用合并工具完全忽略工作树版本,而使用原始三个输入。 但是无论您做什么,通常都可以通过运行git add P
结束此序列。 这就告诉Git的使用合并到现在卸下三个更高阶段的版本,并复制无论是在工作树-after你编辑的工作树版本,例如,或者产生一个新的工具到索引/临时区域作为路径P
的正常,无冲突,零槽条目。 这样可以解决合并冲突。
使用-Xours
或-Xtheirs
告诉Git,它将在哪里声明这样的合并冲突,它应该简单地用另一个冲突更改覆盖一个冲突更改。 冲突永远不会出现! 通常,低级合并过程会将冲突本身放入路径P
下的工作树文件中,并将三个较高级的条目保留在原位。 不过,这一次,这种低级合并过程通过采用left / local /- --ours
更改( -Xours
),或者采用right / remote /- --theirs
更改( -Xtheirs
), 自动解决了冲突 ,而忽略了另一方对这组线的更改。 只要git diff
实际上匹配正确的行集(并非总是如此),那么行的组合可能就有意义。
在任何情况下,使用此X
选项,低级文件合并代码都会按照告诉您的方式为您处理冲突(通过偏爱您告诉它偏向的任何一方),并替换路径的三个较高阶数的条目P
具有正常,零阶段,一切正常的此文件条目。 现在,此特定文件已成功合并,Git继续执行三个提交中的下一组文件。
对于二进制文件,Git甚至不会尝试对文件进行差异化:它们只是从基础开始就被更改,或者未被更改。 它不会尝试使用低级文件合并代码来组合两个差异。 由于没有低级别的文件合并,有什么看你的-X
选项,并有利于在另一侧。
结果是合并完全失败,就好像您根本没有使用-X
。 -X
选项是对低级合并的指令(Git的一部分, 合并了两个文件差异),并且该代码从未运行过。 结果,合并冲突仍保留在索引/登台区域中,并且合并因合并冲突而停止。 您必须自己解决此合并冲突。
您可能会在这里反对说: 我没有运行git merge
,我正在运行git rebase
! 答案是:是的,但是git rebase
本质上基本上只是一系列自动重复的git cherry-pick
命令。 一次樱桃选择会复制一次提交,因此如果rebase需要复制三个提交(例如4--5--6
,则rebase会对这三个提交运行三个Cherry-pick。 每个git cherry-pick
都是通过使用Git 进行合并动词的部分来完成的。 Cherry-pick的合并基础是要复制的提交的父级 ; 左侧或- --ours
提交是Git在复制时“站立”的提交; 右侧或- --theirs
提交是Git正在复制的提交。
一旦完成一次樱桃选择,Git --ours
出了该提交:现在,该提交是--ours
的下一个樱桃选择操作。 也就是说,当您开始时:
D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
并运行git checkout old-branch && git rebase new-branch
,Git首先将提交D
复制到新的提交D'
,然后在C之后:
D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D' <-- temporary
这是一个樱桃选择样式的合并操作; 合并基是D
的父B
,-- --ours
提交是C
一旦合并成功并且提交D'
存在,Git继续将提交E
复制到E'
:
D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D'-E' <-- temporary
这是三个摘樱桃操作中的第二个。 现在,合并基数为D
,- --theirs
提交为E
, --ours
提交为D'
。 如果合并成功,当Git继续复制时,将使用第三个Cherry-pick复制三个提交中的最后一个。 一旦成功,提交图将如下所示:
D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D'-E'-F' <-- temporary
Git现在要做的就是通过将分支名称old-branch
移到此处来完全删除临时分支名称:
D--E--F [abandoned]
/
A--B
\
C <-- new-branch
\
D'-E'-F' <-- old-branch
并完成了基准。
因为每个符号链接实际上都是二进制文件,所以您必须手动合并每个此类文件:使用-Xours
的低级合并代码永远不会运行。 要再次选择--ours
版本,这将是C
的一个,然后是D'
的一个,然后是E'
的一个-您可以运行git checkout --ours -- P
复制插槽2的版本将路径P
放入工作树,然后git add P
将路径P
的工作树版本复制到索引中,作为阶段零,从而解决了冲突。
(这是一个捷径:您可以运行git checkout HEAD -- P
将HEAD
提交的版本复制到索引插槽0和工作树中。由于--ours
或stage-2版本来自 HEAD
,这具有相同的效果,但仅使用一个Git命令。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.