前言
这一节主要介绍Git标签、别名与Git的垃圾回收机制。git
1、
Git
标签(
tag
)
1.标签的实质
标签与分支十分类似,都是指向某一次提交;而且,它们的值都为各自指向提交的SHA1值;可是,不一样于会随着提交的变化而变化的分支,一旦给某次提交添加了标签,该标签就永远不会发生变化。正则表达式
「注意」:标签标识的是某一次提交,此次提交能够是任何分支上的任何一次提交。小程序
两类标签
Git标签有两种:微信小程序
「轻量级标签」(lightweight):不可添加注释;
「带有附注的标签」(annotated):能够添加注释;
❝
Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels.微信
❞
以上是git官方文档对两种标签的说明,大意是:带注释的标签用于发布,而轻量级标签则用于私人或临时对象。框架
「何时打标签呢?」ide
「版本发布」:通常master分支都会做为项目的发布分支,当项目开发到了一个成熟的阶段,准备在master分支进行发布时。通常都会在master分支的当前提交上打上一个相似"v1.2"的标签;学习
好比Vue框架:测试
image-20200418125541646
能够看到有许多标签,而且能够在releases选项中查看标签和发布版本:优化
image-20200418125721571
「版本管理」:能够经过标签的形式记录项目某一阶段的状态,方便管理;
好比管理学习微信小程序时每一个知识点的代码:
image-20200418165957032
「查看标签文件」
以下图所示,分别给master分支的提交mas2添加一个轻量级标签v1.0和一个带有附注的标签v2.0:
image-20200418122516160
❝
git dog为git log --all --decorate --oneline --graph的别名,后面会讲解;
❞
随后,查看存储标签文件的.git/refs/tags目录:
image-20200418123105227
能够看到:
tags目录下存储着添加的标签文件v1.0和v2.0;
分别打开标签文件v1.0和v2.0,它们的值都是一个SHA1值,而且与添加标签时所在提交mas2的SHA1值6920a6e...相等。
emm...等等!并不相等呀,只有v1.0的值与提交mas2的SHA1值相等,而与v2.0的值并不相等!
为何给同一次提交mas2添加的标签,它们的SHA1值会不相等呢?这是由于v1.0是轻量级标签,而v2.0是带有附注的标签。
虽然两个标签标记的都是同一次提交,可是它们的构造不同:
轻量级标签v1.0直接将此次提交的SHA1值做为本身的SHA1值;
而带附注的标签v2.0会建立一个tag对象,它的SHA1值是tag对象的SHA1值;
这就是轻量级标签与带有附注标签的区别。不过这两个标签仍然会指向同一次提交,以下图所示:
image-20200418124847587
2.建立标签
git tag <tag_name>
建立一个轻量级标签:
image-20200311143441005
git tag -a <tag_name> -m '注释'
建立一个带有附注的标签:
image-20200311143555121
3.查看标签
git tag
显示添加的全部标签:
image-20200418140044357
也能够添加--list参数:
image-20200418140101235
以下图所示:切换了分支tag仍然存在,说明tag与分支并无关系,它标识的是某次特定的提交:
image-20200418140210619
git show <tag_name>
如图所示,在master分支上进行两次提交,每次为文件test.txt添加一行内容而且打上标签。其中v1.0为轻量级标签,v2.0为带有附注的标签:
image-20200418164206660
随后,使用git show查看标签的内容:
「轻量级标签」:
image-20200418164502188
如图所示,该指令会显示标签v1.0所指向的提交;而且,会输出标签指向提交与上一次提交的比较结果;因为标签v1.0指向的提交为master分支的第一次提交,因此上一次提交为null。所以比较结果显示:相比于上一次提交,标签指向的提交1st在文件test.txt中新增了一行1st;
「带注释的标签」:
image-20200418165301312
相比于轻量级标签,带附注的标签是一个对象,能够存储附注和打标签的人和时间等信息,因此显示的信息多一些;从图中的比较结果可知,相比于上一次提交1st,标签v2.0指向的提交2nd为文件test.txt新增了一行2nd;
4.查找标签
git tag -l <tag_name>
该方式支持正则表达式查找;
image-20200418140732354
如上图所示:
v表示搜索全部以v开头的标签;
?2表示搜索任意开头,但包含2的标签;
5.将标签推送到远程
要将标签推送到远程仓库,首先要创建本地仓库与远程仓库的联系,好比能够采用:
git push -u origin master
创建本地master分支与远程master分支的联系,并进行一次推送:
image-20200418143423585
git push origin <tag_name>
这种方法能够推送指定的本地标签到远程仓库,例如将本地master分支上的标签v1.0推送到远程仓库:
image-20200418143541273
执行上述指令后,对应的远程仓库gitTest中就会出现相应的tag信息了:
image-20200418143927912
也能够在releases选项中,查看tag和Releases信息:
image-20200418144230515
image-20200418144207107
「也能够同时推送多个本地标签到远程仓库」:
git push origin v2.0 v3.0
image-20200418144612359
以上的命令都是简写形式,「完整写法为」:
git push origin refs/tags/v4.0:refs/tags/v4.0
image-20200418144755135
git push origin --tag
该方法能够一次性推送全部的本地标签到远程仓库:
image-20200418144952994
也能够采用简写命令:
//下面的tag能够写成tags,效果同样 git push --tag
image-20200418145049074
6.删除远程标签
固然,咱们能够直接在远程仓库上删除远程标签。可是,最好的方式仍是采用命令行进行删除。删除远程标签的方法与删除远程分支的方法很是相似,一样有两种方法:
git push origin :<tag_name>
这种方法至关于推送一个空的标签到远程仓库,由此达到删除的效果。好比删除远程仓库中的标签v3.0:
git push origin :v3.0
image-20200418154504982
这样远程仓库中的标签V3.0就被删除了:
image-20200418154554319
可是本地仓库中对应的标签V3.0并无被删除:
image-20200418154631370
上述指令为简写,「完整写法以下」:
git push origin :refs/tags/v3.0
image-20200418154906969
git push origin --delete <tag_name>
该方法采用了更加语义化的参数--delete,实现远程标签的删除:
git push origin --delete v2.0
image-20200418155134748
一样成功地删除了远程仓库中的标签v2.0:
image-20200418155216230
可是,本地的标签v2.0也没有被删除:
image-20200418155311429
采用下列的完整写法,效果是同样的:
git push origin --delete tag v2.0
image-20200418155513090
❝
不难发现,删除「远程分支」和「远程标签」的方法是「同样」的。
❞
7.删除本地标签
git tag -d <tag_name>
如经过如下命令删除标签v3.0:
git tag -d v3.0
image-20200418155616562
8.切换标签
git checkout <tag_name>
如图所示,在master分支上进行了三次提交,而且添加了相应的标签:
image-20200418161353146
当咱们经过checkout命令切换到标签v2.0时:
image-20200418161526176
可见,会出现游离的提交。此时查看各分支状态:
image-20200418161655468
如上图所示,当前处于标签v2.0指向的提交,而且切换标签的过程当中改变了HEAD指针的指向。可是,并无改变分支master的指向。过程以下图所示:
image-20200418162458123
也就是说,切换标签与使用reset进行版本回退十分类似。只不过切换标签只改变了HEAD指针的指向,会形成游离的提交。如有须要能够建立一个新分支进行保存。
9.拉取标签
在下图所示的状况中,本地仓库mygit与远程仓库有公共的提交历史(同源),而且不发生合并冲突的状况下(具体可参考Git应用详解第六讲:Git协做与Git pull常见问题):
image-20200418160517111
能够直接经过git pull将远程仓库的标签拉取下来,并建立本地仓库中没有的标签:
image-20200418160737829
2、
Git
别名
1.设置git命令别名
git config <做用域> alias.<别名> '<命令>'
别名就是一个替代,使用一个简短的字符串来代替经常使用的长命令。好比能够经过以下命令,使用别名bra来替代branch命令:
git config --global alias.bra branch
image-20200417184645237
当命令较为简短时,能够省略命令两边的单引号:
image-20200417184803691
在上述命令中:
--global表示设置的别名做用域为系统用户,即该用户对全部的git仓库均可以使用这个别名;其他还有仓库做用域--loacl,系统做用域--system;
alias.br表示更改别名为br;
再日后的branch表示须要起别名的命令,能够是带参数的长命令,此时不能省略命令两边的单引号:
git config --global alias.dog 'log --all --decorate --oneline --graph'
image-20200413171109680
因为上面配置的别名做用域为系统用户,该配置会写入gitconfig配置文件。打开该文件能够看到写入的「别名配置」:
❝
「补充」:使用vi ~/.gitconfig能够直接打开gitconfig这个文件(记得加点),不管当前所处的路径是什么;
❞
image-20200417185537264
也就是说能够直接经过修改gitconfig文件的alias选项来设置别名,可是「不建议」。
这样,经过别名就能够简化一些经常使用的命令了,好比git status、git checkout等:
image-20200417185854925
2.设置外部命令别名
像gitk这样的外部命令,是没有git前缀的。设置别名的方法与设置git提供的命令有所不一样,要按照以下格式设置:
git config <做用域> alias.<别名> '<!外部命令>'
感叹号表示这是一个外部命令;
注意要加上单引号,不用加git前缀;
好比在系统用户做用域下,将git ui设置为gitk的别名:
git config --global alias.ui '!gitk'
设置完成后,该配置会被写入系统用户的配置文件gitconfig中:
image-20200417190632295
随后直接使用git ui便能打开gitk界面:
image-20200417190558949
「补充」:设置了别名后,原来的命令仍然有效。
3、垃圾回收:
Git gc
所谓gc就是垃圾回收机制,实际使用较少;它的做用是「清理没必要要的文件并优化本地存储库」。
为了演示它的做用,设置如下测试环境:
首先,在本地仓库mygit建立master和dev两个分支,并将它们推送到远程仓库:
image-20200418105755292
而后,给本地仓库mygit添加一个轻量级标签v1.0和一个带有附注的标签v2.0:
image-20200418110041381
此时.git/refs目录下的各文件以下所示:
image-20200418110228125
heads目录存储的是本地分支信息,remote目录存储的是远程分支信息,tags目录存储的是标签信息,符合预期。
随后,执行git gc命令:
image-20200418110332080
再次查看.git/refs目录:
image-20200418110544449
能够看到refs目录及其子目录下的文件消失了,可是.git目录下多了一个packed-refs文件。事实上,refs目录下的文件不是消失了,而是被打包到了packed-refs文件中。打开packed-refs文件:
image-20200418111206150
能够看到执行git gc后refs目录及其子目录下的文件都被「压缩打包」到packed-refs文件中了。从图中能够看到轻量级标签v1.0只占一行,而带附注的标签v2.0占两行:
其中第6行和第8行的SHA1值是相同的,这是由于两个标签都是给同一次提交上添加的;而带附注的标签v2.0中的另一行信息(第7行)表示的则是tag对象的SHA1值;打包完以后,再次「修改文件」,或者「添加分支」,新增的内容仍是会在.git/refs目录下显示,而不会被打包到packed-refs文件中,须要从新执行git gc才会被打包。