这些提交实际上是在这些分支的所有上。
考虑以下问题。我们从一个名为main 的分支开始。名称 main 定位一个特定的提交,具有一个特定的哈希 ID H。 (真正的哈希 ID 是一些看起来很丑的东西,因此使用大写字母作为替代。)
提交H 包含两件事:
- 源快照——在最新提交中出现的每个文件的完整副本;和
- 一些元数据,其中包含提交人的姓名和电子邮件地址等内容。
提交H 中的元数据包含一些较早 提交的哈希ID。我们说H 指向较早的提交,而名称main 指向提交H:
<-H <--main
散列 ID inside H 本身就是其他提交的,所以让我们画出那个提交,我们称之为G:
<-G <-H <--main
当然,较早的提交 G 指向一些更早的提交 F:
... <-F <-G <-H <--main
等等。最终我们用完了“早期”提交,因为我们击中了第一个。有点懒得画箭头了,这给了我们一个更完整的画面:
A--B--C--D--E--F--G--H <-- main (HEAD)
HEAD 这个名字告诉我们我们做了一个git checkout main。
现在让我们添加一个新的分支名称,例如develop。 Git 要求 分支名称包含一些有效的现有提交的哈希 ID。我们应该使用哪些提交?最明显的候选是当前和最新的提交,H:
A--B--C--D--E--F--G--H <-- develop, main (HEAD)
如果我们现在检查develop,特殊名称HEAD 会记住分支名称是当前分支,移动:
A--B--C--D--E--F--G--H <-- develop (HEAD), main
我们仍在使用提交H。我们只是通过名称develop 使用它。
提交在哪个分支上?很明显,所有提交都在两个分支上。
当我们进行 new 提交时,Git 会:
- 将所有源文件打包为一个新快照;
- 添加一些元数据,使用来自
user.name 和user.email 的正确名称和电子邮件地址(这些不可能是谎言:它们一定是对的!),“现在”作为日期和时间,以及以此类推。
Git 将从我们或 -m 参数获取日志消息,并将使用 当前提交 作为新提交将向后指向的位置:
I
/
A--B--C--D--E--F--G--H <-- main
因为我们是on branch develop,正如git status 所说,Git 会将new 提交I 的哈希ID 存储到HEAD 所附加的名称中,develop ,像这样:
I <-- develop (HEAD)
/
A--B--C--D--E--F--G--H <-- main
分支develop 上有哪些提交? 全部,和以前一样。 only 提交I 不是在develop 上。 所有提交都在develop。只是通过H 的提交在main 上也。
如果我们现在git checkout main,Git 会:
- 删除所有伴随提交
I的文件;
- 提取所有提交
H的文件;和
- 将
HEAD 附加到main。
结果是:
I <-- develop
/
A--B--C--D--E--F--G--H <-- main (HEAD)
除了HEAD 的附加位置外,存储库中的提交和分支没有任何变化;但我们的工作树(和 Git 的索引或 暂存区)现在已更新以再次匹配提交 H。
如果我们现在创建另一个新的分支名称topic,并切换到它,我们会得到:
I <-- develop
/
A--B--C--D--E--F--G--H <-- main, topic (HEAD)
如果我们现在再次新提交,我们会得到:
I <-- develop
/
A--B--C--D--E--F--G--H <-- main
\
J <-- topic (HEAD)
这就是 Git 中分支的全部意义所在:它们是查找提交的方法。
提交才是最重要的。每个提交都以特殊的、只读的、仅 Git 的、压缩的和重复数据删除的形式存储 每个 文件的完整快照。因此,如果提交 H、I 和 J 都共享他们的大部分文件,他们实际上是共享这些文件,即使每个文件都有自己的完整副本。 (启用此共享因为内容是只读的。)
要查看任何给定提交中的更改,Git 只需按照提交的内部向后箭头指向其父项。那个父母也有一个快照。两个提交中相同的任何文件都不会更改,并且由于 Git 正在执行重复数据删除,它可以非常快速地发现这一点。对于 更改的文件,Git 会比较它们的内容以查看更改的内容,并向您显示差异(这是按需计算的,而不是存储在提交中)。
要使分支“独立”,只需将它们全部启动得足够远。在这里,分支topic 和分支develop 都从main 上的提交H 开始。这意味着我们所做的更改,然后用于制作快照 I 或 J,不会反映在另一个提交中,该提交以来自 H 的文件副本开始。
(稍后,如果我们去 merge 分支 develop 和 topic,提交 H——最好的共享提交,在 两个 分支——都非常重要。)