12.Git tag 标签

标签即 tag ,是人为的对提交进行命名,可以更方便更直观地表达某个提交的意义。例如:用标签名称为 V2.0.0 来表示软件的发布版本对应的某个提交。

接下来,将对一个名为 Hello World 的示例版本库进行研究,详情的介绍 tag 的创建、删除和共享,这个版本库不需要从头建立,直接从 Github (https://github.com/ossxp-com/hello-world.git)上克隆。

  1. 先在本地创建一个镜像,用作本地用户的共享版本库:
tag1.png

现在,本地建立了一个裸版本库 /git_study/repos/hello-world.git

  1. 分别在用户 user3user4 各自的工作区中克隆这个裸版本库,操作方式跟之前一样:
tag2.png

准备工作已经完成了,下面将详情介绍 tag 的相关用法。

**一、显示 tag **

  1. 不带任何参数执行 git tag 命令,可查看当前版本库的 tag 列表:
tag3.png
  1. 创建 tag 的时候可以添加说明,要在显示 tag 的时候同时显示这个说明,要使用 -n{num} 参数 ,表示显示最多 num 行描述说明:
tag4.png

上图输出显示了一行的 tag 说明 。

  1. 还可以使用通配符对输出进行过滤,只显示匹配通配符规则的 tag
tag5.png

上图输出表示只显示 v1 版本的 tag ,注意不是 -1-l (是字母) 。

二、命令 git log 查看日志时,加上 --decorate 参数可以看到提交对应的 tag 以及其他引用(Git 版本较高时,默认就会显示,不用加上该参数):

tag6.png

三、 使用命令 git describe

该命令将显示一个易记的名称,如果当前提交恰好打上了 tag ,则显示这个 tag 名称,如果当前提交没有对应的 tag ,但是在其祖先提交上有创建 tag ,则使用 {tag}-{num}-g{commit} 的格式显示。 {tag} 表示距离当前提交最近的 tag 名称,{num} 是该 tag 的提交和当前提交之间的距离(即 tag 提交之后的第几次提交),{commit} 就是当前提交的精简提交 ID

tag7.png

上图显示当前提交是最近的 tag(jx/v1.0) 之后的第 2 次提交,提交 IDd901dd8

四、创建 tag

使用 git tag 命令创建 tag ,有以下几种创建方式:

  • git tag {tagname} {commit} :创建轻量级 tag

  • git tag -m {msg} {tagname} {commit} :创建带说明的 tag

其实还有带签名的 tag ,这里就不介绍了。创建 tag 时,需要输入 tag 名称和一个可选的提交 ID ,如果不提供,则基于 HEAD 创建 tag

  1. 创建轻量级 tag

这种 tag 最简单,无须输入任何说明信息,来演示一下:

先创建一个空提交,接着在这个提交上创建轻量级 tag ,名称为 mytag ,再查看一下本地 tag 列表:

tag8.png

实现方式: 当创建了 mytag 后,会在版本库的 .git/refs/tags 目录下创建一个新文件,这个文件保存的是一个提交 ID ,该提交 ID 对应的内容就是打上标签的那个提交的内容,所以可以用 tag 名称替代指定的提交 ID

tag9.png
tag10.png

轻量级 tag 的缺点:创建过程没有记录,因此无法知道是谁创建的 tag ,以及何时创建的 tag 。强烈建议创建带说明的 tag ,不要以用这种偷懒的方式来创建 tag 。另外,git describe 命令默认不使用轻量级 tag 来生成版本描述字符串,除非加上 --tags 参数。

tag11.png

上图可知,如果不加上 --tags 参数,默认还是以之前 jx/v1.0 这个标签为基准。

  1. 创建带说明的 tag

还是先创建一个空提交,然后通过 -m 参数来创建带说明的 tag ,再查看一下本地 tag 列表:

tag12.png
tag13.png

实现方式: 当创建了 mytag2 后,会在版本库的 .git/refs/tags 目录下创建一个新文件,这个文件保存的是一个对象哈希值 ,该哈希值指向的不再是一个提交,而是一个 tag 对象,该对象内容也不是我们熟系的提交对象的内容,而是包含了创建 tag 时的说明,以及对应的提交 ID 等信息,通过其记录的提交 ID 才能查到具体的提交信息。**

tag14.png
tag15.png

至此,Git 对象库的四类对象都涉及到了,分别是 commit 对象、tree 对象、blob 对象和 tag 对象。

虽然 mytag2 本身是一个 tag 对象,但在很多 git 命令中,可以直接将其看作一个提交,就跟轻量级 tag 一样,当作提交 ID 来使用。

注意:通过 git rev-parse mytag2 这种方式得到的 IDtag 对象ID ,并不是提交对象的 ID ,需要根据对象 ID 来查看具体提交的 ID

tag16.png

上图所示,第一种方式获取的是对象 ID ,下面四种方式都可以获得 mytag2 对象所指向的提交对象的 ID

五、删除 tag

如果 tag 创建在错误的提交上,或者对 tag 的命名不满意,可以使用 git tag -d {tagname} 来删除指定的 tag ,下面将删除 mytag 本地标签 。

tag17.png

tag 没有类似 reflog 的变更机制,删除之后不易恢复,要慎用。在删除 tag 的命令输出中,会显示该 tag 所对应的提交 ID ,发现删错了,赶紧补救还来得及。

Git 并没有提供对 tag 进行重命名的命令,如果对 tag 命名不满意,可以删除旧的再重新用新的名称创建。

根据上图输出中的提交 ID ,将 tag 进行恢复:git tag mytag 3205ed1

注意:不要随意更改 tag ,因为 tag 从概念上讲是对历史提交的一个标记,不应该随意变动。另一个原因是 tag 已经被人同步,如果修改了 tag ,已经同步该 tag 的用户并不会自动更新,这会导致一个相同名称的 tag 在不同用户的版本库中的指向不同。

六、共享 tag 到远程版本库

  1. 查看一下用户 user3 当前的状态,发现有两个新的提交(两个提交都打上了 tag ),再执行 git push 命令进行推送,最后通过 git ls-remote origin my* 查看远程以 my 开头的引用信息(tag 也算是引用的一种),发现本地创建的 tag 并没有一起推送到远程。需要在 git push 命令中显式将 tag 推送到远程:
tag18.png
tag19.png

上图可知:可以推送指定单个 tag ( git push origin mytag ) 。也可以通过通配符来批量推送( git push origin refs/tags/* ),通过 git ls-remote origin my* 命令可以看到远程版本库已经同步本地的 tag 了。

总结:创建的 tag 默认不会跟随分支的推送而推送,从而避免了不同用户本地创建的 tag 都自动推送导致的 tag 杂乱,而且不同用户相同的 tag 名称还会互相覆盖。

  1. 其他用户如果执行 git fetchgit pull 操作,能自动将 tag 进行同步吗?演示一下:

用户 user4 执行 git pull 之后,再查看一下本地的 tag 列表:

tag20.png
tag21.png

其实从 git pull 操作的输出中已经可以看到,在获取远程共享版本库的提交的同时,也获取到了新的 tag

  1. tag 能够自动同步吗?来演示一下:
  • tag 是可以被强制更新的,通过添加 -f 参数。用户 user4 强制更新 mytag2 ,修改其描述说明和指向的提交 ID
tag22.png
  • 再显式地对这个 tag 进行推送,要加上 -f 参数来强制推送才行:
tag23.png
  • 切换到用户 user3 ,执行 git pull 操作 ,发现没有获取到新的 tag (默认不会自动同步已经存在的 tag ),必须显式地执行拉回操作。要在 git pull 的参数中使用引用表达式(用冒号分隔的引用名称或通配符)。下图的命令表示用远程共享版本库的引用 refs/tag/mytag2 覆盖本地版本库的同名引用 (冒号左侧是本地,右侧是远程)。
tag24.png

总结:

  1. tag 要进行推送共享,必须进行显式推送。执行 fetchpull 操作只能自动从远程版本库获取tag ,并在本地版本库中创建。

  2. 只会将获取的远程分支所包含的 tag 同步到本地,而不会将远程版本库的其他分支中的 tag 获取到本地。

  3. 如果本地已有同名的 tag ,默认不会自动同步,即使两者的指向不同。

  4. tag 被推送共享之后,最好不要再去修改。

七、删除远程版本库的 tag

删除本地的 tag 非常简单,使用 git tag -d {tagname} 就行了,如何删除已经推送到远程版本库的 tag 呢?方法也很简单,直接在本地版本库执行命令如下命令就行:git push {remote-url} : {tagname}

该命令的最后一个参数实际上是一个引用表达式,引用表达式一般的格式为:{ref}:{ref} 。该推送命令使用的引用表达式冒号前的引用被省略了,表示将一个空值推送到远程版本库对应的引用中,也就是删除远程版本库中相关的引用。该命令不仅可以用于删除 tag ,也可以用来删除远程版本库的分支(下一节再讲)。

将远程版本库中的标签 mytag2 进行删除:

tag25.png

可以看到,远程的 mytag2 的确被删除了,但是本地的 mytag2 还是在的,因为我们并没有执行 git tag -d mytag2

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容