如果我从这段历史开始:
* 505421e - (HEAD -> stage4) go to stage 4
* 307978f - (stage3) go to stage 3
* d8ab213 - steb b
* 49cbef9 - (stage2) step a
* 6e4a2ed - (stage1) go to stage 1
* 3ca2d7d - do something
* 5ce596d - (stage0) go to stage 0
* 0c8487b - foo
* ccfb7c9 - bar
我执行git rebase -i ccfb7c9
以更改foo
提交,然后分支stage0–stage3
将不再具有与stage4
相同的提交历史记录,并且不会拥有已更新foo
提交。如何让他们拥有相同的历史?
答案 0 :(得分:1)
你是对的。不幸的是,Git没有任何东西能够以正确的方式实现这一目标"。 定义"对"有点困难。在这里,虽然我有一个特定的定义 1 并开始编写一个程序来做到这一点。对于所有奇怪的角落案件来说都太难了,我放弃了它。
这里的基本问题是git rebase
通过复制提交工作,就像git cherry-pick
一样(使用交互式rebase让你在此过程中进行一些额外的更改)。< sup> 2 新副本具有新的,不同的哈希ID。 3 创建副本后,Git重新指向一个分支名称 - 当前的分支,无论你何时启动git rebase
- 到最后一次这样复制的提交。
换句话说,在这种情况下,你有Git副本:
0c8487b - foo
5ce596d - (stage0) go to stage 0
3ca2d7d - do something
505421e - (HEAD -> stage4) go to stage 4
按此顺序(最早到最晚),一次一个。在第一步,您进行某些更改 - 只要您更改某些内容,它就不重要 - 这样新的提交会获得一些新的,不同的哈希ID,例如{{ 1}}(可能实际上并非如此,但这让我们将其称为&#34;新提交1&#34;)。此新提交的父提交是cccccc1
,它是标记为ccfb7c9
的提交,因此新历史记录将重新加入旧历史记录。
然后Git复制第二个提交bar
,即5ce596d - (stage0) go to stage 0
。 cccccc2
的父级是cccccc2
,与cccccc1
完全不同,强制将其作为不同的提交。 Git继续复制所有八个提交,最后一个提交5ce596d
或许;然后Git更改名称cccccc8
,以便命名提交stage4
。
因此,当您现在通过从名称cccccc8
找到Git的提交开始查看历史记录时,您会看到 new 历史记录。但是Git没有改变任何其他名称:stage4
,例如,仍然标识提交stage3
,而307978f
仍然标识提交stage0
1}}。因此,如果您从任何那些名称开始查看历史记录,您会看到原始提交系列。
你需要的是让Git将每个标签从其原始哈希移动到新哈希。问题在于识别所有这些事情:应该移动哪些标签? (你可能希望有些人故意保留旧的提交,有些人要移动。)就此而言,哪个提交是正确的新提交?如果在交互式rebase期间,我选择拆分一些提交并合并其他提交,该怎么办?
简单而强力的解决方案是手动强制您想要更改的任何名称,以指向新的提交。运行5ce596d
并记下每个名称的新旧提交ID,然后运行:
git log --all --decorate --oneline --graph
你完成了。或者,只需完全删除其中一些分支名称,因为您可以从git branch -f stage0 newhash0
git branch -f stage1 newhash1
git branch -f stage2 newhash2
git branch -f stage3 newhash3
(自动移动)和向后工作开始查找提交。
1 我喜欢的定义涉及构造分支名称,因此名称具有更多的语义而不仅仅是#34;指向提交的原始指针&#34;。这个结构的表单也很难:它应该使用名称层次结构,还是应该有stage4
个条目将分支名称分组为&#34;超级分支&#34;?
2 有些git config
命令实际上运行git rebase
,有些则不运行git cherry-pick
。交互式rebase是真正运行git cherry-pick
以及git commit --amend
和其他棘手项目的案例之一。
3 任何Git对象的哈希ID都严格由其内容决定,所以如果&#34; copy&#34;与相同位的原始位100%相同 - 您使用相同的哈希ID,即,您只需重新使用原始位。但是一旦你做了任何改变,序列中某些提交的哈希ID就会改变,这会强制每个&#34;下游&#34; (child)提交一个不同的父哈希ID,它也会改变每个下游提交。