Git應用詳解第八講:Git標簽、別名與Git gc


前言

前情提要:Git應用詳解第七講:Git refspec與遠程分支的重要操作

這一節主要介紹Git標簽、別名與Git的垃圾回收機制。

一、Git標簽(tag)

1.標簽的實質

標簽與分支十分相似,都是指向某一次提交;並且,它們的值都為各自指向提交的SHA1值;但是,不同於會隨着提交的變化而變化的分支,一旦給某次提交添加了標簽,該標簽就永遠不會發生變化。

注意:標簽標識的是某一次提交,這次提交可以是任何分支上的任何一次提交。

兩類標簽

Git標簽有兩種:

  • 輕量級標簽lightweight):不可添加注釋;
  • 帶有附注的標簽annotated):可以添加注釋;

Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels.

以上是git官方文檔對兩種標簽的說明,大意是:帶注釋的標簽用於發布,而輕量級標簽則用於私人或臨時對象。

什么時候打標簽呢?

  • 版本發布:一般master分支都會作為項目的發布分支,當項目開發到了一個成熟的階段,准備在master分支進行發布時。一般都會在master分支的當前提交上打上一個類似"v1.2"的標簽;

    比如Vue框架:

    image-20200418125541646

    可以看到有許多標簽,並且可以在releases選項中查看標簽和發布版本:

    image-20200418125721571

  • 版本管理:可以通過標簽的形式記錄項目某一階段的狀態,方便管理;

    比如管理學習微信小程序時每個知識點的代碼:

    image-20200418165957032

查看標簽文件

如下圖所示,分別給master分支的提交mas2添加一個輕量級標簽v1.0和一個帶有附注的標簽v2.0

image-20200418122516160

git doggit log --all --decorate --oneline --graph的別名,后面會講解;

隨后,查看存儲標簽文件的.git/refs/tags目錄:

image-20200418123105227

可以看到:

  • tags目錄下存儲着添加的標簽文件v1.0v2.0
  • 分別打開標簽文件v1.0v2.0,它們的值都是一個SHA1值,並且與添加標簽時所在提交mas2SHA16920a6e...相等。
  • emm...等等!並不相等呀,只有v1.0的值與提交mas2SHA1值相等,而與v2.0的值並不相等!
  • 為什么給同一次提交mas2添加的標簽,它們的SHA1值會不相等呢?這是因為v1.0是輕量級標簽,而v2.0是帶有附注的標簽。

雖然兩個標簽標記的都是同一次提交,但是它們的構造不一樣:

  • 輕量級標簽v1.0直接將這次提交的SHA1值作為自己的SHA1值;

  • 而帶附注的標簽v2.0會創建一個tag對象,它的SHA1值是tag對象的SHA1值;

這就是輕量級標簽與帶有附注標簽的區別。不過這兩個標簽仍然會指向同一次提交,如下圖所示:

image-20200418124847587

2.創建標簽

git tag <tag_name>

創建一個輕量級標簽:

image-20200311143441005

git tag -a <tag_name> -m '注釋'

創建一個帶有附注的標簽:

image-20200311143555121

3.查看標簽

git tag

顯示添加的所有標簽:

image-20200418140044357

也可以添加--list參數:

image-20200418140101235

如下圖所示:切換了分支tag仍然存在,說明tag與分支並沒有關系,它標識的是某次特定的提交:

image-20200418140210619

git show <tag_name>

如圖所示,在master分支上進行兩次提交,每次為文件test.txt添加一行內容並且打上標簽。其中v1.0為輕量級標簽,v2.0為帶有附注的標簽:

image-20200418164206660

隨后,使用git show查看標簽的內容:

  • 輕量級標簽:

    image-20200418164502188

    如圖所示,該指令會顯示標簽v1.0所指向的提交;並且,會輸出標簽指向提交與上一次提交的比較結果;由於標簽v1.0指向的提交為master分支的第一次提交,所以上一次提交為null。因此比較結果顯示:相比於上一次提交,標簽指向的提交1st在文件test.txt中新增了一行1st

  • 帶注釋的標簽:

    image-20200418165301312

    相比於輕量級標簽,帶附注的標簽是一個對象,可以存儲附注和打標簽的人和時間等信息,所以顯示的信息多一些;從圖中的比較結果可知,相比於上一次提交1st,標簽v2.0指向的提交2nd為文件test.txt新增了一行2nd

4.查找標簽

git tag -l <tag_name>

該方式支持正則表達式查找;

image-20200418140732354

如上圖所示:

  • v*表示搜索所有以v開頭的標簽;
  • ?2*表示搜索任意開頭,但包含2的標簽;

5.將標簽推送到遠程

要將標簽推送到遠程倉庫,首先要建立本地倉庫與遠程倉庫的聯系,比如可以采用:

git push -u origin master

建立本地master分支與遠程master分支的聯系,並進行一次推送:

image-20200418143423585

git push origin <tag_name>

這種方法可以推送指定的本地標簽到遠程倉庫,例如將本地master分支上的標簽v1.0推送到遠程倉庫:

image-20200418143541273

執行上述指令后,對應的遠程倉庫gitTest中就會出現相應的tag信息了:

image-20200418143927912

也可以在releases選項中,查看tagReleases信息:

image-20200418144230515

image-20200418144207107

也可以同時推送多個本地標簽到遠程倉庫

git push origin  v2.0 v3.0

image-20200418144612359

以上的命令都是簡寫形式,完整寫法為:

git push origin refs/tags/v4.0:refs/tags/v4.0

image-20200418144755135

git push origin --tag

該方法可以一次性推送所有的本地標簽到遠程倉庫:

image-20200418144952994

也可以采用簡寫命令:

//下面的tag可以寫成tags,效果一樣
git push --tag

image-20200418145049074

6.刪除遠程標簽

當然,我們可以直接在遠程倉庫上刪除遠程標簽。但是,最好的方式還是采用命令行進行刪除。刪除遠程標簽的方法與刪除遠程分支的方法非常類似,同樣有兩種方法:

git push origin :<tag_name>

這種方法相當於推送一個空的標簽到遠程倉庫,由此達到刪除的效果。比如刪除遠程倉庫中的標簽v3.0

git push origin :v3.0

image-20200418154504982

這樣遠程倉庫中的標簽V3.0就被刪除了:

image-20200418154554319

但是本地倉庫中對應的標簽V3.0並沒有被刪除:

image-20200418154631370

上述指令為簡寫,完整寫法如下

git push origin :refs/tags/v3.0

image-20200418154906969

git push origin --delete <tag_name>

該方法采用了更加語義化的參數--delete,實現遠程標簽的刪除:

git push origin --delete v2.0

image-20200418155134748

同樣成功地刪除了遠程倉庫中的標簽v2.0

image-20200418155216230

但是,本地的標簽v2.0也沒有被刪除:

image-20200418155311429

采用下列的完整寫法,效果是一樣的:

git push origin --delete tag v2.0

image-20200418155513090

不難發現,刪除遠程分支遠程標簽的方法是一樣的。

7.刪除本地標簽

git tag -d <tag_name>

如通過以下命令刪除標簽v3.0

git tag -d v3.0

image-20200418155616562

8.切換標簽

git checkout <tag_name>

如圖所示,在master分支上進行了三次提交,並且添加了相應的標簽:

image-20200418161353146

當我們通過checkout命令切換到標簽v2.0時:

image-20200418161526176

可見,會出現游離的提交。此時查看各分支狀態:

image-20200418161655468

如上圖所示,當前處於標簽v2.0指向的提交,並且切換標簽的過程中改變了HEAD指針的指向。但是,並沒有改變分支master的指向。過程如下圖所示:

image-20200418162458123

也就是說,切換標簽與使用reset進行版本回退十分相似。只不過切換標簽只改變了HEAD指針的指向,會造成游離的提交。若有需要可以創建一個新分支進行保存。

9.拉取標簽

在下圖所示的情況中,本地倉庫mygit與遠程倉庫有公共的提交歷史(同源),並且不發生合並沖突的情況下(具體可參考Git應用詳解第六講:Git協作與Git pull常見問題):

image-20200418160517111

可以直接通過git pull將遠程倉庫的標簽拉取下來,並創建本地倉庫中沒有的標簽:

image-20200418160737829

二、Git別名

1.設置git命令別名

git config <作用域> alias.<別名> '<命令>'

別名就是一個替代,使用一個簡短的字符串來代替常用的長命令。比如可以通過如下命令,使用別名bra來替代branch命令:

git config --global alias.bra branch 

image-20200417184645237

當命令較為簡短時,可以省略命令兩邊的單引號:

image-20200417184803691

在上述命令中:

  • --global表示設置的別名作用域為系統用戶,即該用戶對所有的git倉庫都可以使用這個別名;其余還有倉庫作用域--loacl,系統作用域--system

  • alias.br表示更改別名為br

  • 再往后的branch表示需要起別名的命令,可以是帶參數的長命令,此時不能省略命令兩邊的單引號:

    git config --global alias.dog 'log --all --decorate --oneline --graph'
    

    image-20200413171109680

由於上面配置的別名作用域為系統用戶,該配置會寫入gitconfig配置文件。打開該文件可以看到寫入的別名配置

補充:使用vi ~/.gitconfig可以直接打開gitconfig這個文件(記得加點),無論當前所處的路徑是什么;

image-20200417185537264

也就是說可以直接通過修改gitconfig文件的alias選項來設置別名,但是不建議

這樣,通過別名就可以簡化一些常用的命令了,比如git statusgit checkout等:

image-20200417185854925

2.設置外部命令別名

gitk這樣的外部命令,是沒有git前綴的。設置別名的方法與設置git提供的命令有所不同,要按照如下格式設置:

git config <作用域> alias.<別名> '<!外部命令>'
  • 感嘆號表示這是一個外部命令;
  • 注意要加上單引號,不用加git前綴;

比如在系統用戶作用域下,將git ui設置為gitk的別名:

 git config --global alias.ui '!gitk'

設置完成后,該配置會被寫入系統用戶的配置文件gitconfig中:

image-20200417190632295

隨后直接使用git ui便能打開gitk界面:

image-20200417190558949

補充:設置了別名后,原來的命令仍然有效。

三、垃圾回收:Git gc

所謂gc就是垃圾回收機制,實際使用較少;它的作用是清理不必要的文件並優化本地存儲庫

為了演示它的作用,設置以下測試環境:

  • 首先,在本地倉庫mygit創建masterdev兩個分支,並將它們推送到遠程倉庫:

    image-20200418105755292

  • 然后,給本地倉庫mygit添加一個輕量級標簽v1.0和一個帶有附注的標簽v2.0

    image-20200418110041381

此時.git/refs目錄下的各文件如下所示:

image-20200418110228125

heads目錄存儲的是本地分支信息,remote目錄存儲的是遠程分支信息,tags目錄存儲的是標簽信息,符合預期。

隨后,執行git gc命令:

image-20200418110332080

再次查看.git/refs目錄:

image-20200418110544449

可以看到refs目錄及其子目錄下的文件消失了,但是.git目錄下多了一個packed-refs文件。事實上,refs目錄下的文件不是消失了,而是被打包到了packed-refs文件中。打開packed-refs文件:

image-20200418111206150

可以看到執行git gcrefs目錄及其子目錄下的文件都被壓縮打包packed-refs文件中了。從圖中可以看到輕量級標簽v1.0只占一行,而帶附注的標簽v2.0占兩行:

  • 其中第6行和第8行的SHA1值是相同的,這是因為兩個標簽都是給同一次提交上添加的;
  • 而帶附注的標簽v2.0中的另外一行信息(第7行)表示的則是tag對象的SHA1值;

打包完之后,再次修改文件,或者添加分支,新增的內容還是會在.git/refs目錄下顯示,而不會被打包到packed-refs文件中,需要重新執行git gc才會被打包。

以上就是本節的全部內容,經過這一節的學習,相信你已經能夠熟練運用Git標簽和別名來提高開發效率了。下一節將會詳細介紹git cherry-pickgit rebase,我們下一節再見!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM