Git詳解之二 Git基礎(第二部分)

移動文件python

不像其餘的 VCS 系統,Git 並不跟蹤文件移動操做。若是在 Git 中重命名了某個文件,倉庫中存儲的元數據並不會體現出這是一次更名操做。不過 Git 很是聰明,它會推斷出究竟發生了什麼,至於具體是如何作到的,咱們稍後再談。git

既然如此,當你看到 Git 的 mv 命令時必定會困惑不已。要在 Git 中對文件更名,能夠這麼作:github

$ git mv file_from file_to

它會恰如預期般正常工做。實際上,即使此時查看狀態信息,也會明白無誤地看到關於重命名操做的說明:shell

$ git mv README.txt README 
$ git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # renamed: README.txt -> README #

其實,運行 git mv 就至關於運行了下面三條命令:編程

$ mv README.txt README 
$ git rm README.txt $ 
git add README

      如此分開操做,Git 也會意識到這是一次更名,因此無論何種方式都同樣。固然,直接用 git mv 輕便得多,不過有時候用其餘工具批處理更名的話,要記得在提交前刪除老的文件名,再添加新的文件名。api

2.3  查看提交歷史

在提交了若干更新以後,又或者克隆了某個項目,想回顧下提交歷史,可使用 git log 命令查看。bash

接下來的例子會用我專門用於演示的 simplegit 項目,運行下面的命令獲取該項目源代碼:服務器

git clone git://github.com/schacon/simplegit-progit.git

而後在此項目中運行 git log,應該會看到下面的輸出:網絡

$ git log 
commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit


     默認不用任何參數的話,git log 會按提交時間列出全部的更新,最近的更新排在最上面。看到了嗎,每次更新都有一個 SHA-1 校驗和、做者的名字和電子郵件地址、提交時間,最後縮進一個段落顯示提交說明。app

git log 有許多選項能夠幫助你搜尋感興趣的提交,接下來咱們介紹些最經常使用的。

咱們經常使用 -p 選項展開顯示每次提交的內容差別,用 -2 則僅顯示最近的兩次更新

$ git log -p -2 
commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file

在作代碼審查,或者要快速瀏覽其餘協做者提交的更新都做了哪些改動時,就能夠用這個選項。此外,還有許多摘要選項能夠用,好比 --stat,僅顯示簡要的增改行數統計:

$ git log --stat 
commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number Rakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code lib/simplegit.rb | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ lib/simplegit.rb | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 0 deletions(-)

每一個提交都列出了修改過的文件,以及其中添加和移除的行數,並在最後列出全部增減行數小計。還有個經常使用的--pretty 選項,能夠指定使用徹底不一樣於默認格式的方式展現提交歷史。好比用oneline 將每一個提交放在一行顯示,這在提交數很大時很是有用。另外還有 short,full 和fuller 能夠用,展現的信息或多或少有些不一樣,請本身動手實踐一下看看效果如何。

$ git log --pretty=oneline 
ca82a6dff817ec66f44342007202690a93763949 changed the version number 
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code 
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

但最有意思的是 format,能夠定製要顯示的記錄格式,這樣的輸出便於後期編程提取分析,像這樣:

$ git log --pretty=format:"%h - %an, %ar : %s" 
ca82a6d - Scott Chacon, 11 months ago : changed the version number 085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code a11bef0 - Scott Chacon, 11 months ago : first commit

表 2-1 列出了經常使用的格式佔位符寫法及其表明的意義。

選項 說明 %H 提交對象(commit)的完整哈希字串 %h 提交對象的簡短哈希字串 %T 樹對象(tree)的完整哈希字串 %t 樹對象的簡短哈希字串 %P 父對象(parent)的完整哈希字串 %p 父對象的簡短哈希字串 %an 做者(author)的名字 %ae 做者的電子郵件地址 %ad 做者修訂日期(能夠用 -date= 選項定製格式) %ar 做者修訂日期,按多久之前的方式顯示 %cn 提交者(committer)的名字 %ce 提交者的電子郵件地址 %cd 提交日期 %cr 提交日期,按多久之前的方式顯示 %s 提交說明

你必定奇怪_做者(author)_和_提交者(committer)_之間究竟有何差異,其實做者指的是實際做出修改的人,提交者指的是最後將此 工做成果提交到倉庫的人。因此,當你爲某個項目發佈補丁,而後某個核心成員將你的補丁併入項目時,你就是做者,而那個核心成員就是提交者。咱們會在第五章 再詳細介紹二者之間的細微差異。

用 oneline 或 format 時結合 --graph 選項,能夠看到開頭多出一些 ASCII 字符串表示的簡單圖形,形象地展現了每一個提交所在的分支及其分化衍合狀況。在咱們以前提到的 Grit 項目倉庫中能夠看到:

$ git log --pretty=format:"%h %s" --graph * 
2d3acf9 ignore errors from SIGCHLD on trap * 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit |\ | * 420eac9 Added a method for getting the current branch. * | 30e367c timeout code and tests * | 5a09431 add timeout protection to grit * | e1193f8 support for heads with slashes in them |/ * d6016bc require time for xmlschema * 11d191e Merge branch 'defunkt' into local

以上只是簡單介紹了一些 git log 命令支持的選項。表 2-2 還列出了一些其餘經常使用的選項及其釋義。

選項 說明 -p 按補丁格式顯示每一個更新之間的差別。 --stat 顯示每次更新的文件修改統計信息。 --shortstat 只顯示 --stat 中最後的行數修改添加移除統計。 --name-only 僅在提交信息後顯示已修改的文件清單。 --name-status 顯示新增、修改、刪除的文件清單。 --abbrev-commit 僅顯示 SHA-1 的前幾個字符,而非全部的 40 個字符。 --relative-date 使用較短的相對時間顯示(好比,「2 weeks ago」)。 --graph 顯示 ASCII 圖形表示的分支合併歷史。 --pretty 使用其餘格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和 format(後跟指定格式)。

限制輸出長度

除了定製輸出格式的選項以外,git log 還有許多很是實用的限制輸出長度的選項,也就是隻輸出部分提交信息。以前咱們已經看到過 -2 了,它只顯示最近的兩條提交,實際上,這是 - 選項的寫法,其中的 n 能夠是任何天然數,表示僅顯示最近的若干條提交。不過實踐中咱們是不太用這個選項的,Git 在輸出全部提交時會自動調用分頁程序(less),要看更早的更新只需翻到下頁便可。

另外還有按照時間做限制的選項,好比 --since 和 --until。下面的命令列出全部最近兩週內的提交:

$ git log --since=2.weeks

你能夠給出各類時間格式,好比說具體的某一天(「2008-01-15」),或者是多久之前(「2 years 1 day 3 minutes ago」)。

還能夠給出若干搜索條件,列出符合的提交。用 --author 選項顯示指定做者的提交,用 --grep 選項搜索提交說明中的關鍵字。(請注意,若是要獲得同時知足這兩個選項搜索條件的提交,就必須用--all-match 選項。)

若是隻關心某些文件或者目錄的歷史提交,能夠在 git log 選項的最後指定它們的路徑。由於是放在最後位置上的選項,因此用兩個短劃線(--)隔開以前的選項和後面限定的路徑名。

表 2-3 還列出了其餘經常使用的相似選項。

選項 說明 -(n) 僅顯示最近的 n 條提交 --since, --after 僅顯示指定時間以後的提交。 --until, --before 僅顯示指定時間以前的提交。 --author 僅顯示指定做者相關的提交。 --committer 僅顯示指定提交者相關的提交。

來看一個實際的例子,若是要查看 Git 倉庫中,2008 年 10 月期間,Junio Hamano 提交的但未合併的測試腳本(位於項目的 t/ 目錄下的文件),能夠用下面的查詢命令:

$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \ 
--before="2008-11-01" --no-merges -- t/ 
5610e3b - Fix testcase failure when extended attribute acd3b9e - Enhance hold_lock_file_for_{update,append}() f563754 - demonstrate breakage of detached checkout wi d1a43f2 - reset --hard/read-tree --reset -u: remove un 51a94af - Fix "checkout --track -b newbranch" on detac b0ad11e - pull: allow "git pull origin $something:$cur

Git 項目有 20,000 多條提交,但咱們給出搜索選項後,僅列出了其中知足條件的 6 條。

使用圖形化工具查閱提交歷史

有時候圖形化工具更容易展現歷史提交的變化,隨 Git 一同發佈的 gitk 就是這樣一種工具。它是用 Tcl/Tk 寫成的,基本上至關於 git log 命令的可視化版本,凡是git log 能夠用的選項也都能用在 gitk 上。在項目工做目錄中輸入 gitk 命令後,就會啓動圖 2-2 所示的界面。

圖 2-2. gitk 的圖形界面

上半個窗口顯示的是歷次提交的分支祖先圖譜,下半個窗口顯示當前點選的提交對應的具體差別。

 

2.4  撤消操做

     任什麼時候候,你都有可能須要撤消剛纔所作的某些操做。接下來,咱們會介紹一些基本的撤消操做相關的命令。請注意,有些操做並不老是能夠撤消的,因此請務必謹慎當心,一旦失誤,就有可能丟失部分工做成果。

修改最後一次提交

有時候咱們提交完了才發現漏掉了幾個文件沒有加,或者提交信息寫錯了。想要撤消剛纔的提交操做,可使用 --amend選項從新提交:

$ git commit --amend

       此命令將使用當前的暫存區域快照提交。若是剛纔提交完沒有做任何改動,直接運行此命令的話,至關於有機會從新編輯提交說明,但將要提交的文件快照和以前的同樣。啓動文本編輯器後,會看到上次提交時的說明,編輯它確認沒問題後保存退出,就會使用新的提交說明覆蓋剛纔失誤的提交。

若是剛纔提交時忘了暫存某些修改,能夠先補上暫存操做,而後再運行 --amend 提交:

$ git commit -m 'initial commit' 
$ git add forgotten_file 
$ git commit --amend

上面的三條命令最終只是產生一個提交,第二個提交命令修正了第一個的提交內容。

取消已經暫存的文件

接下來的兩個小節將演示如何取消暫存區域中的文件,以及如何取消工做目錄中已修改的文件。不用擔憂,查看文件狀態的時候就提示了該如何撤消,因此不須要死記硬背。來看下面的例子,有兩個修改過的文件,咱們想要分開提交,但不當心用git add . 全加到了暫存區域。該如何撤消暫存其中的一個文件呢?其實,git status 的命令輸出已經告訴了咱們該怎麼作:

$ git add . 
$ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: README.txt # modified: benchmarks.rb #

就在 「Changes to be committed」 下面,括號中有提示,可使用 git reset HEAD ... 的方式取消暫存。好吧,咱們來試試取消暫存 benchmarks.rb 文件:

$ git reset HEAD benchmarks.rb 
benchmarks.rb: locally modified $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: README.txt # # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: benchmarks.rb #

這條命令看起來有些古怪,先別管,能用就行。如今 benchmarks.rb 文件又回到了以前已修改未暫存的狀態。

取消對文件的修改

若是以爲剛纔對 benchmarks.rb 的修改徹底沒有必要,該如何取消修改,回到以前的狀態(也就是修改以前的版本)呢?git status 一樣提示了具體的撤消方法,接着上面的例子,如今未暫存區域看起來像這樣:

# Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: benchmarks.rb #

在第二個括號中,咱們看到了拋棄文件修改的命令(至少在 Git 1.6.1 以及更高版本中會這樣提示,若是你還在用老版本,咱們強烈建議你升級,以獲取最佳的用戶體驗),讓咱們試試看:

$ git checkout -- benchmarks.rb 
$ git status 
# On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: README.txt #

       能夠看到,該文件已經恢復到修改前的版本。你可能已經意識到了,這條命令有些危險,全部對文件的修改都沒有了,由於咱們剛剛把以前版本的文件複製過 來重寫了此文件。因此在用這條命令前,請務必肯定真的再也不須要保留剛纔的修改。若是隻是想回退版本,同時保留剛纔的修改以便未來繼續工做,能夠用下章介紹 的 stashing 和分支來處理,應該會更好些。

記住,任何已經提交到 Git 的均可以被恢復。即使在已經刪除的分支中的提交,或者用 --amend 從新改寫的提交,均可以被恢復(關於數據恢復的內容見第九章)。因此,你可能失去的數據,僅限於沒有提交過的,對 Git 來講它們就像從未存在過同樣。

2.5  遠程倉庫的使用

要參與任何一個 Git 項目的協做,必需要了解該如何管理遠程倉庫。遠程倉庫是指託管在網絡上的項目倉庫,可能會有好多個,其中有些你只能讀,另外有些能夠寫。同他人協做開發某 個項目時,須要管理這些遠程倉庫,以便推送或拉取數據,分享各自的工做進展。管理遠程倉庫的工做,包括添加遠程庫,移除廢棄的遠程庫,管理各式遠程庫分 支,定義是否跟蹤這些分支,等等。本節咱們將詳細討論遠程庫的管理和使用。

查看當前的遠程庫

要查看當前配置有哪些遠程倉庫,能夠用 git remote 命令,它會列出每一個遠程庫的簡短名字。在克隆完某個項目後,至少能夠看到一個名爲 origin 的遠程庫,Git 默認使用這個名字來標識你所克隆的原始倉庫:

$ git clone git://github.com/schacon/ticgit.git 
Initialized empty Git repository in /private/tmp/ticgit/.git/ remote: Counting objects: 595, done. remote: Compressing objects: 100% (269/269), done. remote: Total 595 (delta 255), reused 589 (delta 253) Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done. Resolving deltas: 100% (255/255), done. $ cd ticgit $ git remote origin


也能夠加上 -v 選項(譯註:此爲 --verbose 的簡寫,取首字母),顯示對應的克隆地址:

$ git remote -v origin	git://github.com/schacon/ticgit.git

若是有多個遠程倉庫,此命令將所有列出。好比在個人 Grit 項目中,能夠看到:

$ cd grit 
$ git remote -v 
bakkdoor git://github.com/bakkdoor/grit.git cho45 git://github.com/cho45/grit.git defunkt git://github.com/defunkt/grit.git koke git://github.com/koke/grit.git origin git@github.com:mojombo/grit.git

這樣一來,我就能夠很是輕鬆地從這些用戶的倉庫中,拉取他們的提交到本地。請注意,上面列出的地址只有 origin 用的是 SSH URL 連接,因此也只有這個倉庫我能推送數據上去(咱們會在第四章解釋緣由)。

添加遠程倉庫

要添加一個新的遠程倉庫,能夠指定一個簡單的名字,以便未來引用,運行 

git remote add [shortname] [url]:
$ git remote origin 
$ git remote add pb git://github.com/paulboone/ticgit.git $ git remote -v origin	git://github.com/schacon/ticgit.git pb	git://github.com/paulboone/ticgit.git

如今能夠用字串 pb 指代對應的倉庫地址了。好比說,要抓取全部 Paul 有的,但本地倉庫沒有的信息,能夠運行git fetch pb:

$ git fetch pb 
remote: Counting objects: 58, done. remote: Compressing objects: 100% (41/41), done. remote: Total 44 (delta 24), reused 1 (delta 0) Unpacking objects: 100% (44/44), done. From git://github.com/paulboone/ticgit * [new branch] master -> pb/master * [new branch] ticgit -> pb/ticgit

如今,Paul 的主幹分支(master)已經徹底能夠在本地訪問了,對應的名字是 pb/master,你能夠將它合併到本身的某個分支,或者切換到這個分支,看看有些什麼有趣的更新。

從遠程倉庫抓取數據

正如以前所看到的,能夠用下面的命令從遠程倉庫抓取數據到本地:

$ git fetch [remote-name]

此命令會到遠程倉庫中拉取全部你本地倉庫中尚未的數據。運行完成後,你就能夠在本地訪問該遠程倉庫中的全部分支,將其中某個分支合併到本地,或者只是取出某個分支,一探究竟。(咱們會在第三章詳細討論關於分支的概念和操做。)

若是是克隆了一個倉庫,此命令會自動將遠程倉庫歸於 origin 名下。因此,git fetch origin 會抓取從你上次克隆以來別人上傳到此遠程倉庫中的全部更新(或是上次 fetch 以來別人提交的更新)。有一點很重要,須要記住,fetch 命令只是將遠端的數據拉到本地倉庫,並不自動合併到當前工做分支,只有當你確實準備好了,才能手工合併。

若是設置了某個分支用於跟蹤某個遠端倉庫的分支(參見下節及第三章的內容),可使用 git pull 命令自動抓取數據下來,而後將遠端分支自動合併到本地倉庫中當前分支。在平常工做中咱們常常這麼用,既快且好。實際上,默認狀況下git clone 命令本質上就是自動建立了本地的 master 分支用於跟蹤遠程倉庫中的 master 分支(假設遠程倉庫確實有 master 分支)。因此通常咱們運行git pull,目的都是要從原始克隆的遠端倉庫中抓取數據後,合併到工做目錄中的當前分支。

推送數據到遠程倉庫

項目進行到一個階段,要同別人分享目前的成果,能夠將本地倉庫中的數據推送到遠程倉庫。實現這個任務的命令很簡單:git push [remote-name] [branch-name]。若是要把本地的 master 分支推送到origin 服務器上(再次說明下,克隆操做會自動使用默認的 master 和 origin 名字),能夠運行下面的命令:

$ git push origin master

只有在所克隆的服務器上有寫權限,或者同一時刻沒有其餘人在推數據,這條命令纔會如期完成任務。若是在你推數據前,已經有其餘人推送了若干更新,那 你的推送操做就會被駁回。你必須先把他們的更新抓取到本地,合併到本身的項目中,而後才能夠再次推送。有關推送數據到遠程倉庫的詳細內容見第三章。

查看遠程倉庫信息

咱們能夠經過命令 git remote show [remote-name] 查看某個遠程倉庫的詳細信息,好比要看所克隆的 origin 倉庫,能夠運行:

$ git remote show origin 
* remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with 'git pull' while on branch master master Tracked remote branches master ticgit

除了對應的克隆地址外,它還給出了許多額外的信息。它友善地告訴你若是是在 master 分支,就能夠用 git pull 命令抓取數據合併到本地。另外還列出了全部處於跟蹤狀態中的遠端分支。

上面的例子很是簡單,而隨着使用 Git 的深刻,git remote show 給出的信息可能會像這樣:

$ git remote show origin
 * remote origin URL: git@github.com:defunkt/github.git Remote branch merged with 'git pull' while on branch issues issues Remote branch merged with 'git pull' while on branch master master New remote branches (next fetch will store in remotes/origin) caching Stale tracking branches (use 'git remote prune') libwalker walker2 Tracked remote branches acl apiv2 dashboard2 issues master postgres Local branch pushed with 'git push' master:master

它告訴咱們,運行 git push 時缺省推送的分支是什麼(譯註:最後兩行)。它還顯示了有哪些遠端分支尚未同步到本地(譯註:第六行的caching 分支),哪些已同步到本地的遠端分支在遠端服務器上已被刪除(譯註:Stale tracking branches 下面的兩個分支),以及運行git pull 時將自動合併哪些分支(譯註:前四行中列出的 issues 和 master 分支)。

遠程倉庫的刪除和重命名

在新版 Git 中能夠用 git remote rename 命令修改某個遠程倉庫在本地的簡短名稱,好比想把 pb 改爲paul,能夠這麼運行

$ git remote rename pb paul $ git remote origin paul

注意,對遠程倉庫的重命名,也會使對應的分支名稱發生變化,原來的 pb/master 分支如今成了 paul/master。

碰到遠端倉庫服務器遷移,或者原來的克隆鏡像再也不使用,又或者某個參與者再也不貢獻代碼,那麼須要移除對應的遠端倉庫,能夠運行 git remote rm 命令:

$ git remote rm paul $ git remote origin

2.6  打標籤

同大多數 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 Date: Mon Feb 9 14:45:11 2009 -0800 my version 1.4 commit 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge: 4a447f7... a6b4c97... Author: Scott Chacon 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 " 1024-bit DSA key, ID F721C45A, created 2009-02-09

如今再運行 git show 會看到對應的 GPG 簽名也附在其內:

$ git show 
v1.5 tag v1.5 Tagger: Scott Chacon 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 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 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 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 " 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 Date: Mon Feb 9 15:32:16 2009 -0800 version 1.2 commit 9fceb02d0ae598e95dc970b74767f19372d61af8 Author: Magnus Chacon 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 git@github.com: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 git@github.com: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

如今,其餘人克隆共享倉庫或拉取數據同步後,也會看到這些標籤。

若是須要刪除本地tag

git tag -d v1.5

若是須要刪除遠程tag

用push, 刪除遠程tag
git push origin :refs/tags/v1.5


2.7  技巧和竅門

在結束本章以前,我還想和你們分享一些 Git 使用的技巧和竅門。不少使用 Git 的開發者可能根本就沒用過這些技巧,咱們也不是說在讀過本書後非得用這些技巧不可,但至少應該有所瞭解吧。說實話,有了這些小竅門,咱們的工做能夠變得更簡單,更輕鬆,更高效。

自動完成

若是你用的是 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 commit config

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

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

$ git log --s --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 Date: Tue Aug 26 19:48:51 2008 +0800 test for current head Signed-off-by: Scott Chacon

能夠看出,實際上 Git 只是簡單地在命令中替換了你設置的別名。不過有時候咱們但願運行某個外部命令,而非 Git 的附屬工具,這個好辦,只須要在命令前加上 ! 就行。若是你本身寫了些處理 Git 倉庫信息的腳本的話,就能夠用這種技術包裝起來。做爲演示,咱們能夠設置用 git visual 啓動gitk:

$ git config --global alias.visual "!gitk"
相關文章
相關標籤/搜索