(这也许应该是一个评论,但它太大了,需要很好的格式:-) ...另外,如果你点击一些链接,我似乎心情很古怪......)
理解这一点的关键——我想你已经在那里了,但是让我们把它放在 SO 文章中以便让下一位读者清楚——是这样的:
所有 git refs 最终命名(指向)单个提交。
对于标签(无论是轻量级的还是带注释的)、分支、“远程分支”、git “notes”引用、“stash”等都是如此。他们都命名了一次提交,仅此而已。(好吧,好吧,不完全是:从技术上讲,标签可以命名存储库中的任何对象。事实上,这就是带注释的标签的工作方式:有一个轻量级标签,它命名一个存储库对象,它是带注释的标签,然后带注释的标签命名为提交对象。这也是HEAD
工作原理:它通常命名另一个 ref,然后命名提交。因此,有时您必须从洋葱上剥几层才能命中提交。命名 blob 或树对象是可能的,但通常,实际上什么都没有这样做。)
(提交的“真实名称”当然是 SHA-1 值。)
使分支引用名称“特殊”的原因同样简单:
分支引用是在添加新提交时自动移动到新分支提示的名称。
具体来说,表单的 ref指向某个提交(根据定义,因为名称指向提交)。当您“打开”该分支1并执行一些 git 操作以添加新提交时,例如or or ,git 会将新提交粘贴到存储库中,然后将名称重新指向新提交。这就是它所要做的!refs/heads/branchname
git commit
git merge
git cherry-pick
我们认为的“分支”是通过从尖端开始——名称指向的提交——并使用每个提交的父级或父级向后工作而形成的。如果提交有一个父级,则它是“在分支上”的普通提交。如果它有两个或更多,那就是“合并”,您可以跟随它的所有父项查找合并的内容。如果它根本没有父母,它就是一个根提交(就像一个新仓库中的初始提交——你实际上可以有多个根;例如,git "notes" 就是这样做的)。
如果您将七个分支标签放在一个提交上,那么您现在有七个2名称用于“分支”。如果您将其清除为一个,那么它当然不会那么混乱,但是 git 不会在意任何一种方式。(Git 只关心你是否将其归为零。现在分支仍然存在,但它真的很难找到,它有资格进行垃圾 回收。)
既然我们在这个话题上,让我们也记下“远程分支”。(我从来没有对“远程分支”这个名字很满意,但我没有更好的,所以让我们定义它。)“远程分支”是表单的本地引用,其中rname是远程(例如)和bname是远程上的分支名称,即,如果您登录该远程并查看那里的分支,则后面的部分。你不能“打开”远程分支——如果你git 给你一个“分离的 HEAD” ——但是这些分支名称会自动更新:当你使用refs/remotes/rname/bname
origin
refs/heads/
git checkout origin/master
git fetch
要从远程获取新的提交,您还需要获取新的分支提示。换句话说,不是您将名称移动到新的分支提示中,而是让其他人(在遥控器上)这样做,然后当您从他们那里获取时,您会立即获取他们的最新版本。
1要“在分支上”,HEAD
引用必须是“间接”引用,例如ref: refs/heads/master
. HEAD
相反,当它被“分离”时,它包含一个原始的 SHA-1 值。你仍然可以添加提交;它们被添加到未标记的分支中。中的引用HEAD
使它们不会被垃圾收集。
2或更多,如果有标签。假设没有标签。
3没有脚注三。