因此,我或多或少地熟悉了变基的工作原理,但是直到最近,我通常只做了一个git rebase -i HEAD~20,然后修改了需要修改的地方。
我惊讶地发现这将修改所有20次提交的哈希值,即使我所采取的唯一行动是压倒最后两个提交。
我不确定是什么原因导致其他18次提交的哈希值发生变化,因为他们的父母都没有,他们的内容也没有变化……或者是吗?也许是时间戳记?
还有办法防止这种情况吗?
你可能觉得你没有改变一些提交,但你实际上在几个方面改变了它们:
每个提交都包含其父项的 sha1。因此,更改父项的 sha1 会修改提交,因此其 sha1。散列是链接在一起的,改变过去的任何事情都会改变未来。从技术上讲,这称为Merkle 树。这是 Git 的一个重要属性,因为给定 sha1,它不仅可以保证当前提交的完整性,还可以保证导致它的整个历史记录的完整性(假设您在 sha1 中找不到冲突,但事实已不再如此)今天,但仍然很难找到碰撞)。
每个提交都包含项目当前状态的快照。因此,即使提交看起来相同,因为它引入了相同的差异,它也可能不对应于项目的相同状态(与相同的树对象)。
如前所述,提交包含时间戳(作者的一个时间戳,提交者的一个时间戳,第二个在您变基时更改)。
这将修改所有 20 个提交的哈希值,即使我采取的唯一操作是压缩最后两个。
如果“最后两个”是指历史上最近的两次提交,那么不,它不会。
请具体一点,展示您正在查看的实际证据、您获得的待办事项清单以及您执行的清单。特征太不可靠,容易受到非共享上下文的影响。
例如,根据我的理解,当我压缩最后两个提交时会发生什么:
$ git log --oneline --reverse @{u}..
00f53a2 echo >master6
afcef3e echo >master7
1f55c48 echo >master8
c3197a0 echo >master9
d30bb35 (HEAD -> master) echo >master10
$ GIT_SEQUENCE_EDITOR='sed -i 5s/pick/squash/' git rebase -i
[detached HEAD 16dc80d] echo >master9
Date: Mon Feb 5 09:25:55 2018 -0800
2 files changed, 2 insertions(+)
create mode 100644 master10
create mode 100644 master9
Successfully rebased and updated refs/heads/master.
$ git log --oneline --reverse @{u}..
00f53a2 echo >master6
afcef3e echo >master7
1f55c48 echo >master8
16dc80d (HEAD -> master) echo >master9
$
Run Code Online (Sandbox Code Playgroud)
你可以看到最后两个提交被压缩在一起,所有历史没有改变的提交的 id 保持不变。