Git里程碑

Table of Contents

里程牌即Tag,是对提交进行的命名,这比单纯的commit ID更加形象、直观。

1 显示

  • git tag [-n< num >] [sth*] 参数 -n< num >:创建里程牌时,可以包含一个说明,而这个参数正是用来设置希望看到里程牌说明的行数<num>。 参数 sth*: 表示希望只有符合该规则(通配符)的里程牌被显示。
  • git log 命令的 –decorate 参数可以看到提交对应的里程牌及其引用。
  • git describe [<commit>] --always
    • 若该提交有里程牌,则显示该里程牌的名字, 否则当指定 -always 时,显示精简 commit ID。
    • 若该提交没有里程碑,但其祖先有,则显示<tag>-<num>-g<commit>,表示该提交<commit>与最近的祖先里程碑<tag>的距离是<num>。

2 创建

对一个提交可建立多个里程碑。

2.1 轻量级里程碑

在创建轻量级里程碑时,无需输入描述信息,因此也无法知道是谁在何时创建了该里程碑,所以,这样的里程碑不推荐使用。

创建轻量级里程碑的命令格式: git tag <tagname> [<commit>]

2.2 带说明的里程碑

创建命令格式: git tag -m <msg> <tagname> [<commit>]

  • 创建
    $ echo hello > welcome.txt
    $ git add .
    $ git commit -m "initialize"
    $ git tag -m "this is first tag" 1stTag
    
  • 查看
    $ git log
    commit 810bdebcfbb8fcdb05931735297adbee9a35cffd
    Author: tech-note <Email Addr>
    Date:   Wed Mar 6 07:42:06 2013 +0800
    
        initialize
    $ git log --decorate
    commit 810bdebcfbb8fcdb05931735297adbee9a35cffd (HEAD, tag: 1stTag, master)
    Author: tech-note <Email Addr>
    Date:   Wed Mar 6 07:42:06 2013 +0800
    
        initialize
    $ git tag
    1stTag
    $ git tag -n1
    1stTag          this is first tag
    $ git describe
    1stTag
    
  • 分析
    $ cat .git/refs/tags/1stTag
    e7c62ded7485db24ceee0e691e297eaef684ac57
    $ git cat-file -t e7c62d
    tag
    $ git cat-file -p e7c62d
    object 810bdebcfbb8fcdb05931735297adbee9a35cffd
    type commit
    tag 1stTag
    tagger tech-note <Email Addr> Wed Mar 6 07:44:07 2013 +0800 
    
    this is first tag
    $ git cat-file -t 810bde
    commit
    $ git cat-file -p 810bde
    tree a114e050ce01e14905be557fc3ffc12991984e3e
    author tech-note <Email Addr> 1362526926 +0800
    committer tech-note <Email Addr> 1362526926 +0800
    
    initialize
    $ git cat-file -p 1stTag
    object 810bdebcfbb8fcdb05931735297adbee9a35cffd
    type commit
    tag 1stTag
    tagger tech-note <Email Addr> Wed Mar 6 07:44:07 2013 +0800
    
    this is first tag
    

    可以看出,是创建了一个tag对象,该对象的ID是e7c62d。该对象中记录了,一个commit对象(ID是810bde)、本tag的名称、提交者、说明信息。

2.3 带签名的里程碑

同带说明的里程碑的本质是一样的,都是创建了一个tag对象,但带签名的里程碑多做了一个工作,就是:为tag对象添加GnuPG签名。创建带签名里程碑的前提是:需要安装GnuPG,并建立相应的公钥、私钥对。 略

3 删除

注意,里程碑没有类似reflog这样的记录变更的机制,所以一旦删除,就无法恢复,只能重建了!

$ git tag -d 1stTag
Deleted tag '1stTag' (was e7c62de)

注意到,在删除时,打印出了该里程碑对应的提交ID,可用于重建里程碑。

4 更改

方法就是,重新建立,但需要加上-f参数以强制覆盖已有的里程碑。

5 共享

先做准备工作

$ git init --bare git-share.git
Initialized empty Git repository in c:/Documents and Settings/lhou/git-share.git\
$ git clone git-share.git/ git-user1
Cloning into 'git-user1'...
warning: You appear to have cloned an empty repository.
done.
$ git clone git-share.git/ git-user2
Cloning into 'git-user2'...
warning: You appear to have cloned an empty repository.
done.
$ cd git-user1
$ echo hello > welcome.txt
$ git add .
$ git commit -m "initialize"
[master (root-commit) 39428ad] initialize
 1 file changed, 1 insertion(+)
 create mode 100644 welcome.txt

默认,里程碑是只在本地版本库可见的,不会因为分支的推送而将里程碑也推送到远程版本库的。举例子为证。

$ git tag -m "this is 1st tag" 1stTag
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 223 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To c:/Documents and Settings/lhou/git-share.git/
 * [new branch]      master -> master
$ cd ../git-share.git/
$ git tag -n1

可见,里程碑1stTag并没有被推送到远程版本库中。

但可以显式推送以共享里程碑。

$ git tag -n1
1stTag          this is 1st tag
$ git push origin master 1stTag
Counting objects: 1, done.
Writing objects: 100% (1/1), 170 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To c:/Documents and Settings/lhou/git-share.git/
 * [new tag]         1stTag -> 1stTag
$ git ls-remote origin 1st*
4346b9852c6b773e09374f302a2352ee37147485        refs/tags/1stTag
39428ad1a1864d813f8bd4d362dc609c690aeeac        refs/tags/1stTag^{}
$ cd ../git-share.git/
$ git tag -n1
1stTag          this is 1st tag

如果要将本地建立的所有里程碑都推送到远程版本库,可以使用 git push origin master refs/tags/*

git ls-remote 用于查看远程版本库的引用。

git pull 可以获取到版本库里新的里程碑

$ cd ../git-user2
$ git pull
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
From c:/Documents and Settings/lhou/git-share
 * [new branch]      master     -> origin/master
 * [new tag]         1stTag     -> 1stTag
$ git tag -n1
1stTag          this is 1st tag

当某个里程碑被更改以后,已获取到该里程碑的版本库再次使用git pull操作时,是无法获取到该里程碑的更新的,除非强制更新。

  • 更新里程碑1stTag
    $ git tag -f -m "user2 update 1stTag's msg" 1stTag
    Updated tag '1stTag' (was 4346b98)
    
  • 此里程碑已不是当时的那个里程碑对象了
    $ git rev-parse 1stTag
    9c06e57b82586a7c5751d88d703ccc113b762f49
    $ git cat-file -p 9c06e5
    object 39428ad1a1864d813f8bd4d362dc609c690aeeac
    type commit
    tag 1stTag
    tagger tech-note <Email Addr> Wed Mar 6 15:49:03 2013 +0800
    
    user2 update 1stTag's msg
    
  • 为更新远程版本库里的里程碑1stTag,需显式推送
    $ git push origin 1stTag
    Counting objects: 1, done.
    Writing objects: 100% (1/1), 177 bytes, done.
    Total 1 (delta 0), reused 0 (delta 0)
    To c:/Documents and Settings/lhou/git-share.git/
       4346b98..9c06e57  1stTag -> 1stTag
    $ cd ../git-share.git/
    $ git tag -n1
    1stTag          user2 update 1stTag's msg
    
  • 其他用户使用git pull无法获取到里程碑1stTag的更新
    $ cd ../git-user1
    $ git pull
    Already up-to-date.
    
  • 其他用户可显式的执行获取操作,并覆盖本地的1stTag
    $ git pull origin refs/tags/1stTag:refs/tags/1stTag
    remote: Counting objects: 1, done.
    remote: Total 1 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (1/1), done.
    From c:/Documents and Settings/lhou/git-share
     - [tag update]      1stTag     -> 1stTag
    Already up-to-date.
    $ git tag -n1
    1stTag          user2 update 1stTag's msg
    

删除远程版本库中里程碑

$ git push origin :1stTag
To c:/Documents and Settings/lhou/git-share.git/
 - [deleted]         1stTag
$ git ls-remote origin 1stTag

Last Updated 2015-11-14 Sat 14:43.

Created by Howard Hou with Emacs 24.5.1 (Org mode 8.2.10)