1.3 Git 的三个阶段
由于远程代码库后续存在新的提交,因此实操过程中的结果与书中并不完全一致。根据书中 HEAD
指向的 SHA-1
:34acc370b4d6ae53f051255680feaefaf7f7850d
,可通过以下命令切换到对应版本,并新建一个 newdemo
分支来避免后续版本的干扰:
# Stay the same with the book in a new branch
$ git checkout && git reset --hard 13dcada077e446d3a05ea9cdbc8ecc261a94e42d && git checkout -b newdemo
# Check commit info in advance for use
$ git cat-file -p HEAD | grep tree
tree 34fa038544bcd9aed660c08320214bafff94150b
$ git cat-file -p HEAD^{tree} | grep another-file
100644 blob b50f80ac4d0a36780f9c0636f43472962154a11a another-file.txt
实战练习:
# Repo initialization
$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition.git demo
$ cd demo
# Add new content to another-file.txt
$ echo "Another line" >> another-file.txt
# Check git status
$ git status
# Add modified file and check status again
$ git add another-file.txt
$ git status
# When a file is moved to the staging area, the SHA-1 hash of the file is created and the blob object is written to Git's database. This happens every time a file is added, but if nothing changes for a file, it means that it is already stored in the database. At first, this might seem that the database will grow quickly, but this is not the case. Garbage collection kicks in at times, compressing, and cleaning up the database and keeping only the objects that are required.
# Some more modification
$ echo 'Whoops almost forgot this' >> another-file.txt
# check status
$ git status
# both 'Changes to be committed' and 'Changes not staged for commit' are observed due to the second update
# add again to merge the status
$ git add another-file.txt
$ git status
# Now, all the changes we have made to the file are ready to be committed, and we can record a commit
$ git commit -m 'Another change to another file'
# Error: fatal: empty ident name (for <z@LAPTOP-QVS7NVNN.localdomain>) not allowed
# Config user name and email
$ git config user.email 'john.doe@example.com'
$ git config user.name 'John Doe'
$ git commit -m 'Another change to another file'
[newdemo 9cfa61c] Another change to another file1 file changed, 2 insertions(+)
此时,再次查看 HEAD 信息,可以发现根节点树 root tree
与 another-file.txt
的 SHA-1
都因为 commit
操作更新了:
$ git cat-file -p HEAD | grep tree
tree 162201200b5223d48ea8267940c8090b23cbfb60
# before:
# tree 34fa038544bcd9aed660c08320214bafff94150b
$ git cat-file -p HEAD^{tree} | grep another-file
100644 blob 35d31106c5d6fdb38c6b1a6fb43a90b183011a4b another-file.txt
# before:
# 100644 blob b50f80ac4d0a36780f9c0636f43472962154a11a another-file.txt
然而,文本文件 another-file.txt
在最后提交前添加到暂存区了两次,如果每次 git add
命令都会产生 blob
、tree
以及 commit
对象,那么 Git 仓库中势必会有中间那次 add
操作的对象,被一同计入 Git 数据库。查看该对象可以使用命令 git fsck
:
$ git fsck --dangling
Checking object directories: 100% (256/256), done.
Checking objects: 100% (49/49), done.
dangling blob ad46f2da274ed6c79a16577571a604d3281cd6d9
进一步验证查到的对象:
$ git cat-file -p ad46f2da274ed6c79a16577571a604d3281cd6d9
This is just another file
Another line
验证成功。
个人小结
由于源码库后续有新版本提交(取消了之前的某个促销活动),导致实际代码和书中不完全一致。好在 Git 可以直接切到变更前的版本,才有了上面一系列实操验证内容。不得不说,Git 确实很强大。
现在想想,其实 Git 的用途远远不止源码版本管理,日常生活中只要遇到切换多个历史版本的场景,都可以用 Git 进行管理。前提是对 Git 的基本概念和命令行得相当熟悉才行。这恐怕也是 Git 难以大面积推广的一个重要原因。不过话说回来,掌握了 Git 的知识后,再去看其他行业涉及版本控制的一些场景,基本也是降维打击的存在了。。。