我找不到任何关于Git如何在内部制作rebase的解释.虽然,我没有考虑消息来源.:)
最常见的答案是在基础提交上应用补丁但不是真的.无法将补丁正确应用于(可能)完全更改的文件.还提到了三向合并,但没有确切地说实际上合并了什么.
谢谢
如果你仔细研究Git代码,你会发现事实上有多种不同的内部算法用于rebase.
首先,rebase被拆分成一个否则是非形容词修改的版本(在内部git-rebase--am,默认情况下用于git am应用Git生成的补丁git format-patch)和交互式 rebase(内部git-rebase--interactive).
反过来,交互式rebase 代码使用自己的多种不同算法.(就非交互式代码而言,就此而言,仅在您使用时-k.)
你可以认为这一点,虽然,具有各自提交复制仿佛通过git cherry-pick.git am基于版本的版本存在一些细微的差别,但是说明它们很棘手,而在交互式rebase的情况下,大多数提交确实使用git cherry-pick(查看$(git --exec-path)/git-rebase--interactive并查找Git命令;修复和壁球使用git commit --amend). 编辑:在现代Git(2.12ish及更高版本)中,Git现在使用其"音序器"代替交互式脚本,但效果是相同的.
那么,更有趣的是它的工作方式git am和/或git cherry-pick工作方式.答案很长而且很无聊,可能最好缩短为"去查看源代码",但简短的回答是:首先git am 尝试将更改作为补丁应用,并且只有在失败的情况下,才会回到完整的三位 -合并方式.请参阅-3旗帜以git am获取简要说明.与此同时,git cherry-pick只做一个直接的三方合并.
这里使用的合并基础往往不是那么有用.考虑这个初始DAGlet和git rebase称,拟向复制A到A'和B到B',这些附加承诺之上D:
A--B <-- branch
/
...--*------C--D <-- origin/branch
Run Code Online (Sandbox Code Playgroud)
第一个樱桃选择操作是选择A,因此它A会对提交*(两个分支的合并基础)进行区分.使用该git am方法,Git尝试将其作为补丁应用于顶部D.如果失败了,或者如果你使用产生互动变基git cherry-pick,提交(如果摘樱桃)或每个失败的文件(如果git am-ing)-get通过三方合并过程中运行.
这实际上是相当合理的:我们真的是在尝试重播*至- A处理后*至- D.最终结果是A':
A--B <-- branch
/
...--*------C--D <-- origin/branch
\
A' [detached HEAD]
Run Code Online (Sandbox Code Playgroud)
但是,现在我们复制B,这对于git am生产补丁从去手段A来B.对于适用的补丁部分,我们只应用它们.对于存在冲突的文件,这次我们从A-vs- B和A-vs-中分离A'文件,使用这些差异对每个失败的补丁文件进行低级文件合并. A这里不是一个很好的合并基地; 它总比没有好.
对于actul git cherry-pickrebases,Git使用整个提交A作为合并基础,并在整个树上进行正常的三向合并.每个文件的合并基础是来自提交的文件的版本A.
(如果我们有更多的提交过去B,那么剩下的就会继续.)
很容易看出非交互式必须如此:
git format-patch -k --stdout --full-index --cherry-pick --right-only \
--src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
"$revisions" ${restrict_revision+^$restrict_revision} \
>"$GIT_DIR/rebased-patches"
...
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
Run Code Online (Sandbox Code Playgroud)
代码,因为git am只获取Index:用于构造基本文件的行.在git rebase代码中定位是比较棘手的,因为关键位深埋在sequencer.c中.
| 归档时间: |
|
| 查看次数: |
721 次 |
| 最近记录: |