1. 程式人生 > >Git系統從0到1的完整學習歷程(第三節 標籤和別名學習)

Git系統從0到1的完整學習歷程(第三節 標籤和別名學習)

打標籤

同大多數 VCS 一樣,Git 也可以對某一時間點上的版本打上標籤。

人們在釋出某個軟體版本(比如 v1.0 等等)的時候,經常這麼做。

本節我們一起來學習如何列出所有可用的標籤,如何新建標籤,以及各種不同型別標籤之間的差別。

列顯已有的標籤

列出現有標籤的命令非常簡單,直接執行 git tag 即可:

$ git tag
    v0.1
    v1.3

顯示的標籤按字母順序排列,所以標籤的先後並不表示重要程度的輕重。

我們可以用特定的搜尋模式列出符合條件的標籤。在 Git 自身專案倉庫中,有著超過 240 個標籤,如果你只對 1.4.2 系列的版本感興趣,可以執行下面的命令:

$ git tag -l 'v1.4.2.*'
    v1.4.2.1
    v1.4.2.2
    v1.4.2.3
    v1.4.2.4

新建標籤

Git 使用的標籤有兩種型別:輕量級的(lightweight)和含附註的(annotated)。

輕量級標籤就像是個不會變化的分支,實際上它就是個指向特定提交物件的引用。

而含附註標籤,實際上是儲存在倉庫中的一個獨立物件,它有自身的校驗和資訊,包含著標籤的名字,電子郵件地址和日期,以及標籤說明,標籤本身也允許使用 GNU Privacy Guard (GPG) 來簽署或驗證。

一般我們都建議使用含附註型的標籤

,以便保留相關資訊;當然,如果只是臨時性加註標籤,或者不需要旁註額外資訊,用輕量級標籤也沒問題。

含附註的標籤

建立一個含附註型別的標籤非常簡單,用 -a (譯註:取 annotated 的首字母)指定標籤名字即可:

$ git tag -a v1.4 -m 'my version 1.4'
    $ git tag
    v0.1
    v1.3
    v1.4

而 -m 選項則指定了對應的標籤說明,Git 會將此說明一同儲存在標籤物件中。如果沒有給出該選項,Git 會啟動文字編輯軟體供你輸入標籤說明。

可以使用 git show

 命令檢視相應標籤的版本資訊,並連同顯示打標籤時的提交物件。

$ git show v1.4
    tag v1.4
    Tagger: Scott Chacon <[email protected]>
    Date: Mon Feb 9 14:45:11 2009 -0800

    my version 1.4
    commit 15027957951b64cf874c3557a0f3547bd83b3ff6
    Merge: 4a447f7... a6b4c97...
    Author: Scott Chacon <[email protected]>
    Date: Sun Feb 8 19:02:46 2009 -0800

    Merge branch 'experiment'

我們可以看到在提交物件資訊上面,列出了此標籤的提交者和提交時間,以及相應的標籤說明。

簽署標籤

如果你有自己的私鑰,還可以用 GPG 來簽署標籤,只需要把之前的 -a 改為 -s (譯註: 取 signed 的首字母)即可:

$ git tag -s v1.5 -m 'my signed 1.5 tag'
    You need a passphrase to unlock the secret key for
    user: "Scott Chacon <[email protected]>"
    1024-bit DSA key, ID F721C45A, created 2009-02-09

現在再執行 git show 會看到對應的 GPG 簽名也附在其內:

$ git show v1.5
    tag v1.5
    Tagger: Scott Chacon <[email protected]>
    Date: Mon Feb 9 15:22:20 2009 -0800

    my signed 1.5 tag
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.8 (Darwin)

    iEYEABECAAYFAkmQurIACgkQON3DxfchxFr5cACeIMN+ZxLKggJQf0QYiQBwgySN
    Ki0An2JeAVUCAiJ7Ox6ZEtK+NvZAj82/
    =WryJ
    -----END PGP SIGNATURE-----
    commit 15027957951b64cf874c3557a0f3547bd83b3ff6
    Merge: 4a447f7... a6b4c97...
    Author: Scott Chacon <[email protected]>
    Date: Sun Feb 8 19:02:46 2009 -0800

    Merge branch 'experiment'

稍後我們再學習如何驗證已經簽署的標籤。

輕量級標籤

輕量級標籤實際上就是一個儲存著對應提交物件的校驗和資訊的檔案。要建立這樣的標籤,一個 -a-s 或 -m 選項都不用,直接給出標籤名字即可:

$ git tag v1.4-lw
    $ git tag
    v0.1
    v1.3
    v1.4
    v1.4-lw
    v1.5

現在執行 git show 檢視此標籤資訊,就只有相應的提交物件摘要:

$ git show v1.4-lw
    commit 15027957951b64cf874c3557a0f3547bd83b3ff6
    Merge: 4a447f7... a6b4c97...
    Author: Scott Chacon <[email protected]>
    Date: Sun Feb 8 19:02:46 2009 -0800

    Merge branch 'experiment'

驗證標籤

可以使用 git tag -v [tag-name] (譯註:取 verify 的首字母)的方式驗證已經簽署的標籤。此命令會呼叫 GPG 來驗證簽名,所以你需要有簽署者的公鑰,存放在 keyring 中,才能驗證:

$ git tag -v v1.4.2.1
    object 883653babd8ee7ea23e6a5c392bb739348b1eb61
    type commit
    tag v1.4.2.1
    tagger Junio C Hamano <[email protected]> 1158138501 -0700

    GIT 1.4.2.1

    Minor fixes since 1.4.2, including git-mv and git-http with alternates.
    gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
    gpg: Good signature from "Junio C Hamano <[email protected]>"
    gpg: aka "[jpeg image of size 1513]"
    Primary key fingerprint: 3565 2A26 2040 E066 C9A7 4A7D C0C6 D9A4 F311 9B9A

若是沒有簽署者的公鑰,會報告類似下面這樣的錯誤:

gpg: Signature made Wed Sep 13 02:08:25 2006 PDT using DSA key ID F3119B9A
    gpg: Can't check signature: public key not found
    error: could not verify the tag 'v1.4.2.1'

後期加註標籤

你甚至可以在後期對早先的某次提交加註標籤。比如在下面展示的提交歷史中:

$ git log --pretty=oneline
    15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
    a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
    0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
    6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
    0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
    4682c3261057305bdd616e23b64b0857d832627b added a todo file
    166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
    9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
    964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
    8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

我們忘了在提交 “updated rakefile” 後為此專案打上版本號 v1.2,沒關係,現在也能做。只要在打標籤的時候跟上對應提交物件的校驗和(或前幾位字元)即可:

$ git tag -a v1.2 9fceb02

可以看到我們已經補上了標籤:

$ git tag
    v0.1
    v1.2
    v1.3
    v1.4
    v1.4-lw
    v1.5

    $ git show v1.2
    tag v1.2
    Tagger: Scott Chacon <[email protected]>
    Date: Mon Feb 9 15:32:16 2009 -0800

    version 1.2
    commit 9fceb02d0ae598e95dc970b74767f19372d61af8
    Author: Magnus Chacon <[email protected]>
    Date: Sun Apr 27 20:43:35 2008 -0700

    updated rakefile
    ...

分享標籤

預設情況下,git push 並不會把標籤傳送到遠端伺服器上,只有通過顯式命令才能分享標籤到遠端倉庫。其命令格式如同推送分支,執行 git push origin [tagname] 即可:

$ git push origin v1.5
    Counting objects: 50, done.
    Compressing objects: 100% (38/38), done.
    Writing objects: 100% (44/44), 4.56 KiB, done.
    Total 44 (delta 18), reused 8 (delta 1)
    To [email protected]:schacon/simplegit.git
    * [new tag] v1.5 -> v1.5

如果要一次推送所有本地新增的標籤上去,可以使用 --tags 選項

$ git push origin --tags
    Counting objects: 50, done.
    Compressing objects: 100% (38/38), done.
    Writing objects: 100% (44/44), 4.56 KiB, done.
    Total 44 (delta 18), reused 8 (delta 1)
    To [email protected]:schacon/simplegit.git
    * [new tag] v0.1 -> v0.1
    * [new tag] v1.2 -> v1.2
    * [new tag] v1.4 -> v1.4
    * [new tag] v1.4-lw -> v1.4-lw
    * [new tag] v1.5 -> v1.5

現在,其他人克隆共享倉庫或拉取資料同步後,也會看到這些標籤。

小技巧

自動補全

如果你用的是 Bash shell,可以試試看 Git 提供的自動補全指令碼。下載 Git 的原始碼,進入 contrib/completion 目錄,會看到一個 git-completion.bash 檔案。將此檔案複製到你自己的使用者主目錄中(譯註:按照下面的示例,還應改名加上點:cp git-completion.bash ~/.git-completion.bash),並把下面一行內容新增到你的 .bashrc 檔案中:

source ~/.git-completion.bash

也可以為系統上所有使用者都設定預設使用此指令碼。Mac 上將此指令碼複製到 /opt/local/etc/bash_completion.d 目錄中,Linux 上則複製到 /etc/bash_completion.d/ 目錄中。這兩處目錄中的指令碼,都會在 Bash 啟動時自動載入。

如果在 Windows 上安裝了 msysGit,預設使用的 Git Bash 就已經配好了這個自動補全指令碼,可以直接使用。

在輸入 Git 命令的時候可以敲兩次跳格鍵(Tab),就會看到列出所有匹配的可用命令建議:

$ git co<tab><tab>
    commit config

此例中,鍵入 git co 然後連按兩次 Tab 鍵,會看到兩個相關的建議(命令) commit 和 config。繼而輸入 m<tab> 會自動完成 git commit 命令的輸入。

命令的選項也可以用這種方式自動完成,其實這種情況更實用些。比如執行 git log 的時候忘了相關選項的名字,可以輸入開頭的幾個字母,然後敲 Tab 鍵看看有哪些匹配的:

$ git log --s<tab>
    --shortstat --since= --src-prefix= --stat --summary

這個技巧不錯吧,可以節省很多輸入和查閱文件的時間。

Git 命令別名

Git 並不會推斷你輸入的幾個字元將會是哪條命令,不過如果想偷懶,少敲幾個命令的字元,可以用 git config 為命令設定別名。來看看下面的例子:

$ git config --global alias.co checkout
    $ git config --global alias.br branch
    $ git config --global alias.ci commit
    $ git config --global alias.st status

現在,如果要輸入 git commit 只需鍵入 git ci 即可。而隨著 Git 使用的深入,會有很多經常要用到的命令,遇到這種情況,不妨建個別名提高效率。

使用這種技術還可以創造出新的命令,比方說取消暫存檔案時的輸入比較繁瑣,可以自己設定一下:

$ git config --global alias.unstage 'reset HEAD --'

這樣一來,下面的兩條命令完全等同:

$ git unstage fileA
    $ git reset HEAD fileA

顯然,使用別名的方式看起來更清楚。另外,我們還經常設定 last 命令:

$ git config --global alias.last 'log -1 HEAD'

然後要看最後一次的提交資訊,就變得簡單多了:

$ git last
    commit 66938dae3329c7aebe598c2246a8e6af90d04646
    Author: Josh Goebel <[email protected]>
    Date: Tue Aug 26 19:48:51 2008 +0800

    test for current head

    Signed-off-by: Scott Chacon <[email protected]>

可以看出,實際上 Git 只是簡單地在命令中替換了你設定的別名。不過有時候我們希望執行某個外部命令,而非 Git 的子命令,這個好辦,只需要在命令前加上 ! 就行。如果你自己寫了些處理 Git 倉庫資訊的指令碼的話,就可以用這種技術包裝起來。作為演示,我們可以設定用 git visual 啟動 gitk

$ git config --global alias.visual '!gitk'