我的用例是在历史记录中的特定提交后插入新提交。我有提交的哈希值,之后我需要插入一个新的提交。
让我们说吧 3是我想在下面的历史记录中提交2之后插入的新提交。
1 <-- 2 <-- 4 <-- 5 <-- 6
我在主分支上执行了以下步骤。
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创建了分支临时,在该分支上进行了提交并进行了rebase。希望历史如下所示,
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并不适合他们。如何处理这类冲突?
请帮忙。
答案 0 :(得分:2)
在Git的估算中,名为 P
的符号链接(其中 P
代表{{1}之类的路径})只是一个名为 apps/abc/ps_abc
的文件,类型为&#34; link&#34;其内容为二进制。由于内容是二进制的,Git无法区分它们。你会认为P
会告诉Git使用&#34;我们的&#34;,但它没有,因为它永远不会落入低级代码。
解决方案是选择正确的版本(通过您喜欢的任何方式)并确保它在索引中作为阶段零版本,然后继续操作(在本例中为-Xours
)。 / p>
合并 - 的动词形式合并 - 是从一个共同的起点开始组合变化的过程。这个常见的起点是,在Git中,合并基础提交。 Git使用提交图找到合并库:你用git rebase --continue
检查一些特定的提交,然后告诉Git git checkout mybranch
。这两个名称标识了两个特定的提交; Git查看了每个提交背后的历史,以找到两组工作分歧的最佳起点。
对于在所有三次提交中发生的每个路径 git merge theirbranch
,Git使用<设置 P
的索引/临时区域条目em>所有三个文件,使用包含 P
的每个条目中的插槽来保存尚未合并的文件。基本版本进入插槽1.我们的同一文件的版本在插槽2中,他们的同一文件的版本在插槽3中。然后,当以下所有条件成立时,会发生合并冲突:
P
更改了文件。P
更改了文件。对于 text (非二进制)文件,Git首先观察前三个条件 - 该文件存在于所有三个版本中,但两侧都有变化 - 并且有效地运行了P
从左到右,从左到右。然后,Git可以逐行查看这些更改,并将将组合更改为单个常见更改。
如果此过程失败,Git通常会声明合并冲突并停止。这将在索引中保留暂存插槽1中的文件 git diff
的 merge base 版本,我们的版本在暂存中然后你可以合并这三个文件 - 也许是使用显示冲突的工作树版本,或者可能使用忽略的合并工具,然后将它们合并到第3个文件中的他们的版本。工作树版完全支持原来的三个输入。但无论你做什么,通常都会运行P
来结束这个序列。这告诉Git删除三个更高级的版本并复制工作树中的任何内容现在 - 例如,在您编辑工作树版本之后,或者生成一个新版本使用合并工具 - 将索引/临时区域作为路径 git add P
的正常,未冲突,插槽为零的条目。此解决合并冲突。
使用P
或-Xours
告诉Git它将声明这种合并冲突的位置,它应该简单地覆盖其中一个与另一个冲突的更改。冲突永远不会出现!通常,低级别合并过程会将冲突本身置于路径 -Xtheirs
下的工作树文件中,并保留三个较高级别的条目。不过,这一次,这个低级合并进程通过左/本地/ P
更改(--ours
)或采取正确/远程来自动解决冲突 / -Xours
更改(--theirs
),忽略对方对此行的更改。只要-Xtheirs
实际上匹配了正确的行集 - 这并非总是如此 - 所得到的行组合可能是有意义的。
在任何情况下,使用此git diff
选项,低级文件合并代码会按照您告诉它的方式处理冲突 - 通过支持您告诉它支持的任何一方 - 并替换三个更高级别路径 X
的-stage-number条目,具有正常的,阶段为零,全部与此文件条目良好的条目。所以现在这个特定文件已经成功合并,Git继续进行三次提交中的下一组文件。
使用二进制文件,Git甚至不会尝试对文件进行区分:它们只是因为基础而被更改或不更改。它不会尝试使用低级文件合并代码组合两个差异。由于 没有低级文件合并,因此没有任何内容可以查看您的P
选项,而是支持一方而不是另一方。
结果是合并失败的方式与您根本没有使用-X
完全相同。 -X
选项是低级合并的指令 - Git中结合了两个文件差异的部分 - 该代码从未运行过。因此,合并冲突仍保留在索引/暂存区域中,并且合并将因合并冲突而停止。您必须自己解决此合并冲突。
您可能会在此反对并说:我没有正在运行-X
,我正在运行git merge
!答案是:是的,但是git rebase
基本上只是一系列git rebase
自动重复命令。一个樱桃选择复制一个提交,因此如果rebase需要复制三个提交,例如git cherry-pick
,则rebase在这三个提交上运行三个樱桃选择。每个4--5--6
都是通过使用执行合并动词的Git部分完成的。 cherry-pick的合并基础是被复制的提交的 parent ;左侧或git cherry-pick
提交是提交Git是&#34;站在&#34;因为它复制;而右侧或--ours
提交是Git正在复制的提交。
一旦完成一个挑选,Git就会检查该提交:现在提交--theirs
以进行下一次挑选操作。也就是说,当你开始:
--ours
并运行 D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
,Git将首先将提交git checkout old-branch && git rebase new-branch
复制到新提交D
以便在C之后:
D'
这是一种樱桃挑选式合并操作;合并基础是 D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D' <-- temporary
的父D
,B
提交是提交--ours
。一旦此合并成功并且提交C
,Git就会将提交D'
复制到E
:
E'
这是三次樱桃挑选行动中的第二次。现在,合并基础为 D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D'-E' <-- temporary
,D
提交为--theirs
,E
提交为--ours
。如果此合并成功,Git继续使用第三个樱桃选择复制三个提交中的最后一个。一旦成功,提交图如下所示:
D'
现在Git需要做的就是完全删除临时分支名称移动分支名称 D--E--F <-- old-branch
/
A--B
\
C <-- new-branch
\
D'-E'-F' <-- temporary
:
old-branch
并且已完成rebase。
因为每个符号链接实际上都是二进制文件,所以必须手动合并每个这样的文件:使用 D--E--F [abandoned]
/
A--B
\
C <-- new-branch
\
D'-E'-F' <-- old-branch
的低级合并代码永远不会运行。要再次选择-Xours
版本,这将是--ours
中的那个,然后是C
中的那个,然后是D'
中的那个 - 您可以运行E'
将路径 git checkout --ours -- P
的slot-2版本复制到工作树中,然后P
复制路径 git add P
的工作树版本回到索引作为阶段0,解决冲突。
(有一个快捷方式:您可以运行P
将版本从git checkout HEAD -- P
提交复制到索引槽0并进入工作树。由于HEAD
或stage-2版本来自 --ours
,这具有相同的效果,但只使用一个Git命令。)