Git知识点:分支和标签对比
相同点
(1)分支和标签都以.git/refs 目录下文件形式存在,文件内容都是某个对象的SHA-1哈希值,创建分支或标签相当于往一个文件中写入41个字节(40个字符和1个换行符)。
$ stat --format=%s .git/refs/heads/master
41
$ stat --format=%s .git/refs/tags/v2.0
41
(2)分支和标签都可以根据需要进行创建和删除,删除分支和标签不会影响被指向的原始对象。
(3)切换分支和标签都会导致头指针(HEAD)发生变化。
不同点
(1)分支必须存在,默认分支为master。标签可以不存在。
(2)分支是动态的,它随着每次提交而移动,分支用于持续开发。标签是静态的,它不随着时间的推移而改变,标签用于标记特定的里程碑或发布版本。
(3)分支不会创建任何对象。附注标签会创建标签对象,标签对象再指向某个提交对象。
(4)分支以.git/refs/heads/文件形式存在,文件内容是某个提交对象的SHA-1哈希值。标签以.git/refs/tags/文件形式存在,文件内容是某个提交对象或标签对象的SHA-1哈希值,轻量标签指向某个提交对象,附注标签指向某个标签对象,标签对象再指向某个提交对象。
说明:标签并非必须指向某个提交对象,可以对任意类型的Git对象打标签。
git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>]
<object>
The object that the new tag will refer to, usually a commit. Defaults to HEAD.
# 分支
$ cat .git/refs/heads/master
8cce0ad8acf1a74a52750f6ce6c53ce2d805f383
# git cat-file -t 8cce0ad8acf1a74a52750f6ce6c53ce2d805f383
commit
$ cat .git/refs/heads/feature1
b9a345e45e3bf81d4bd00081bfe823fbab072be6
$ git cat-file -t b9a345e45e3bf81d4bd00081bfe823fbab072be6
commit
# 标签
$ cat .git/refs/tags/v1.0-lw
3f21097b073483bac919a0554d3f10fe71ed1dc5
$ git cat-file -t 3f21097b073483bac919a0554d3f10fe71ed1dc5
commit
$ cat .git/refs/tags/v2.0
cea0857607fdcb14ed035b69be37417a030a01c0
$ git cat-file -t cea0857607fdcb14ed035b69be37417a030a01c0
tag
(5)检出分支时,HEAD指向某个分支,分支再指向某个提交。检出标签时,HEAD直接指向某个提交,这种状态的HEAD称为detached HEAD(分离头指针)。
$ git checkout master
$ cat .git/HEAD
ref: refs/heads/master
$ git checkout v2.0
$ cat .git/HEAD
8cce0ad8acf1a74a52750f6ce6c53ce2d805f383
注意事项
(1)分支和标签可以使用同一个名字来命名。如果这样做,就必须要使用引用全称来区分它们,例如,refs/tags/v1.0和refs/heads/v1.0。
(2)检出标签会导致仓库处于分离头指针状态,如果做了某些修改然后提交它们,新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希值才能访问。因此,如果需要基于标签进行修改,通常需要创建一个新分支进行提交。
$ git checkout -b version2 v2.0
Switched to a new branch 'version2'
代码示例
###### 单分支开发 ######
$ git init example
$ cd example
# 第1次提交
$ touch index.html
$ git add .
$ git commit -m "init commit"
# 第2次提交
$ echo "version1" > index.html
$ git commit -m "update version1" -a
# 第3次提交
$ echo "version2" > index.html
$ git commit -m "update version2" -a
# 打标签
$ git log --pretty=oneline
bcb52d6130cfd0bc1018a7168013c5b5ba6b0313 update version2
576b800e222e7f73711579dcaa3ae50a91f4b29f update version1
f5887c35d70fb209adc0d2a63a2d2757c1aa20e7 init commit
$ git tag -a -m "version 2.0" v2.0 bcb52d6130cfd0bc1018a7168013c5b5ba6b0313
$ git tag v1.0-lw 576b800e222e7f73711579dcaa3ae50a91f4b29f
# 查看标签
$ git tag
v1.0-lw
v2.0
# 检出标签进行提交时,新提交将不属于任何分支
$ git checkout v1.0-lw
$ echo "version3" > index.html
$ git commit -m "update version3" -a
$ git branch
* (HEAD detached from v1.0-lw)
master
###### 多分支开发 ######
# 创建分支1
$ git checkout -b feature1 master
$ echo "feature1" > feature1.html
$ git add .
$ git commit -m "add feature1"
# 创建分支2
$ git checkout -b feature2 master
$ echo "feature2" > feature2.html
$ git add .
$ git commit -m "add feature2"
# 查看分支
$ git branch -a
feature1
* feature2
master
# 当前分支
$ cat .git/HEAD
ref: refs/heads/feature2
说明:基于标签(v1.0-lw)生成的提交(4eac549)不属于任何分支,只能通过提交哈希值才能访问。为了方便访问,可以通过git branch <branchname> 4eac549
基于该提交创建新分支。
转载自:https://juejin.cn/post/7384997446219005992