使用交互式变基添加新提交时的奇怪行为



假设我们有以下工作流程:

D <-HEAD
|
C
|
B
|
A

假设我想在CD之间添加新的提交X,以便它可以:

D 
|
X
|
C
|
B
|
A

所以我用git rebase -i HEAD~2并为提交C选择"编辑",以便当变基进入"编辑"提交C时,我修改 sth,然后使用git add .git commit,之后我应用git rebase --continue结束变基。 但我得到了以下内容:

D
/
X  C
| /
B
|
A

不是我在提交后添加了一个新的提交C吗? 为什么新的提交X是在B之后?

假设我想在 C 和 D 之间添加新的提交 X,以便它可以:

D 
|
X
|
C
|
B
|
A

实际上根本不会这样。

让我水平绘制这些,向右绘制较新的提交,因为我认为这不那么令人困惑(对我来说当然更容易)。 您最初拥有:

...--A--B--C--D   <-- branch

当你执行这种变基(或任何一系列产生你想要的结果的 Git 命令)时,你最终会将旧的提交D复制到一个新的和改进的提交D2D'(我将使用D'表示法)。 这样做的原因是任何提交不能更改这包括其父提交哈希。 现有提交C的哈希 ID 固定在石头中,现有提交D本身固定在石头中,并包含现有提交C的哈希 ID。 因此,必须放弃提交D,转而使用新的和改进的提交。

你根本不打算做任何事情来提交A,所以 Git可以不管它,而不用重新复制它。BC也是如此. 根据您运行git rebase的方式,您可以强制Git 将这些重新复制到新的提交(使用新的和不同的哈希 ID)。 如果这样做,这些新提交将在所有方面与原始提交匹配,但有两个:

  • 它们将具有不同的时间戳。 具体来说,它们将有一个提交者时间戳,该时间戳是使用您强制 Git 进行新提交的当前时间创建的。 每个提交都有两个时间戳,一个用于"作者",一个用于"提交者"。 作者行代表进行原始提交的人,以及他们何时进行;提交者行表示进行提交的人以及时间。 如果作者和提交者行匹配,这是原始提交;如果它们不同,则这是副本。

  • 同时,除了第一个这样的副本外,每个复制的提交都将具有不同的父提交哈希 ID。 这是因为第一个这样的副本本身具有不同的哈希 ID,并且后续副本必须引用新的和改进的(或至少是新的和微妙的不同)提交。

但是,如果您不强制变基进行复制,它只会在可能的情况下保留原始提交。 所以既然不需要改变ABC,Git 就不会了。

但是,要添加X,Git 需要使其父级是现有提交C进行新的提交X

D   <-- branch
/
...--A--B--C--X   <-- HEAD [rebuild in progress]

如果您在构造提交X后检查提交图,您将看到以下内容。

通过git rebase -i和暂停构造提交X后,然后运行git rebase --continue。 这会将现有的提交D复制到新的提交D'

D   <-- branch
/
...--A--B--C--X--D'  <-- HEAD [rebuild in progress]

如果您设法在这一点上停止 Git(例如,将D标记为edit会这样做)并仔细检查提交图,您现在将看到上述内容。 不过,让 Git 继续下去,git rebase的最后一步是移动分支名称并将HEAD重新附加到分支名称,给出:

D   [abandoned]
/
...--A--B--C--X--D'  <-- branch (HEAD)

由于没有可以轻松找到提交D的名称,因此即使使用git log --all --decorate --oneline --graphgit log也不会显示它。 您现在将只看到D'.

如果您不记得原始提交D的实际哈希 ID,它看起来像新提交D'是原始提交D不是! Git 知道它不是,因为 Git 使用哈希 ID来识别提交。分支名称无关紧要:重要的是哈希 ID。

Git 使用分支名称来查找起始哈希 ID,这是链中的最后一个提交。 这就是为什么在这些绘图中,较新的提交位于右侧,我们将分支名称放在最右侧,并带有向后箭头。 Git 总是向后工作:一个名称查找链中的最后一个提交,然后从那里,Git 使用存储的哈希 ID 向后工作,一次一个提交。

(当 Git 命中具有两个或多个向后箭头的合并提交时,Git 仍然必须一次处理一个提交,大多数情况下。 为了处理此问题,这些 Git 命令会保留哈希 ID 队列。 队列是优先级队列,其中优先级较高的提交先于优先级较低的提交进行访问。 使提交优先级更高或更低的因素取决于您提供给git loggit rev-list--topo-order--graph--date-order--committer-date-order或其他排序选项

最新更新