1.13. 更新 HEAD 到新建的 Commit
好,接下来我们来看一下怎么把我们这个 main 分支的这个 HEAD 给它更新到我们新增的这个 commit 上面。
查看 HEAD
➜ plumbing-demo git:(main) ✗ cat .git/HEAD
ref: refs/heads/main
可以看到我们现在不是在一个 detached head 的状态,我们的 HEAD 现在是对一个分支的引用—— refs/heads/main
。所以要更新 head 只需要将我们的这个 main 分支给它前进到我们新的这个 commit 对象上面。
那我们很容易就可以想到,我们只需要把 .git/refs/heads/main
这个文件里面的内容替换为我们刚才用 git commit-tree
这个命令输出的校验和就可以了。
更新 HEAD 到新建的 commit
找不到 refs/heads/main
我们看一下这个文件。
➜ plumbing-demo git:(main) ✗ cat .git/refs/heads/main
cat: .git/refs/heads/main: No such file or directory
它提示我们没有这个文件,这个时候不要惊慌,我们回忆一下我们之前是用 git gc
这个命令来回收我们的这个垃圾的,所以说它已经把我们这个 main 分支的这个引用给它压缩到一个单独的文件里面,压缩到哪里了?我们之前已经分析了它是压缩到了这个 .git/packed-refs
这个文件,
➜ plumbing-demo git:(main) ✗ cat .git/packed-refs
# pack-refs with: peeled fully-peeled sorted
8f809e04a436df0fccab26ac40cdfc8b32d6ee3d refs/heads/main
f37d6c37d7a2f2d0443b839dac7c13e10ac84239 refs/tags/v1.0
^51871d3a84bb13eccd06022e4962ace4b4d02a62
e8d9ca0d12ce5b17be6e9037507835cd9fdf3abc refs/tags/v2.0
^6423242d1225237121d732f1643038ec94f0eaeb
可以看到这个文件里面就有我们的 main 分支的信息。那我们现在要做的是什么?就是把这个 main 分支的这个 ID 给它替换为我们刚才新建的这个 commit object 这个的 ID 就可以了。
不要替换错了ID
注意: 新建 commit object 这个的 ID一定不要复制错了,不然很可能会出现 fatal: your current branch 'main' does not have any commits yet
这个错误。原因就是因为你将错误的 ID 替换进去了,换言之,你将 HEAD 指向了一个并不存在的 ID,那自然就找不到我们之前的 Commit了。
我们把这个(858d8460b8e690f2321e89e5a779d06cb0018236)全部给它复制过来。我们要修改这个文件,直接就用 VIM 编辑器来修改。
如何在 VIM 编辑器中选择整个字符串?
现在我们要选中 8f809e04a436df0fccab26ac40cdfc8b32d6ee3d
,在 VIM 这个编辑器里面怎么选中一个单词呢?在这里可以找到方法:将光标移动到要选中的字符串上,按下 viw
就可以选中了。按 X 删除,然后直接粘贴。
现在的这个 main 分支的这个指针就已经指到了我们的最新的这个 commit了。
检验是否成功
我们可以看一下现在有没有 news-4.html
这个文件
➜ plumbing-demo git:(main) ✗ ll | grep news-4.html
-rw-r--r-- 1 administrator staff 442B Sep 23 12:53 news-4.html
然后我们看一下这个历史它有没有。
➜ plumbing-demo git:(main) git log --oneline -n 2
# result:
858d846 (HEAD -> main) Add 4th news item
8f809e0 update .gitignore
现在就有了。
小结
最近的四小节清晰地展示了,当我们执行 git commit -am 'commit message'
的时候,在幕后运行的所有事情,所以说我们应该感到庆幸,我们平时都不会使用 plumbing 命令。我们最后手动更新了这个 main 分支后的图,就是这个样子: