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