既然是相互協(xié)作,在貢獻(xiàn)代碼的同時(shí),也免不了要維護(hù)管理自己的項(xiàng)目。像是怎么處理別人用 format-patch
生成的補(bǔ)丁,或是集成遠(yuǎn)端倉庫上某個(gè)分支上的變化等等。但無論是管理代碼倉庫,還是幫忙審核收到的補(bǔ)丁,都需要同貢獻(xiàn)者約定某種長期可持續(xù)的工作方式。
如果想要集成新的代碼進(jìn)來,最好局限在特性分支上做。臨時(shí)的特性分支可以讓你隨意嘗試,進(jìn)退自如。比如碰上無法正常工作的補(bǔ)丁,可以先擱在那邊,直到有時(shí)間仔細(xì)核查修復(fù)為止。創(chuàng)建的分支可以用相關(guān)的主題關(guān)鍵字命名,比如 ruby_client
或者其它類似的描述性詞語,以幫助將來回憶。Git 項(xiàng)目本身還時(shí)常把分支名稱分置于不同命名空間下,比如 sc/ruby_client
就說明這是 sc
這個(gè)人貢獻(xiàn)的。 現(xiàn)在從當(dāng)前主干分支為基礎(chǔ),新建臨時(shí)分支:
$ git branch sc/ruby_client master
另外,如果你希望立即轉(zhuǎn)到分支上去工作,可以用 checkout -b
:
$ git checkout -b sc/ruby_client master
好了,現(xiàn)在已經(jīng)準(zhǔn)備妥當(dāng),可以試著將別人貢獻(xiàn)的代碼合并進(jìn)來了。之后評估一下有沒有問題,最后再?zèng)Q定是不是真的要并入主干。
如果收到一個(gè)通過電郵發(fā)來的補(bǔ)丁,你應(yīng)該先把它應(yīng)用到特性分支上進(jìn)行評估。有兩種應(yīng)用補(bǔ)丁的方法:git apply
或者 git am
。
如果收到的補(bǔ)丁文件是用 git diff
或由其它 Unix 的 diff
命令生成,就該用 git apply
命令來應(yīng)用補(bǔ)丁。假設(shè)補(bǔ)丁文件存在 /tmp/patch-ruby-client.patch
,可以這樣運(yùn)行:
$ git apply /tmp/patch-ruby-client.patch
這會(huì)修改當(dāng)前工作目錄下的文件,效果基本與運(yùn)行 patch -p1
打補(bǔ)丁一樣,但它更為嚴(yán)格,且不會(huì)出現(xiàn)混亂。如果是 git diff
格式描述的補(bǔ)丁,此命令還會(huì)相應(yīng)地添加,刪除,重命名文件。當(dāng)然,普通的 patch
命令是不會(huì)這么做的。另外請注意,git apply
是一個(gè)事務(wù)性操作的命令,也就是說,要么所有補(bǔ)丁都打上去,要么全部放棄。所以不會(huì)出現(xiàn) patch
命令那樣,一部分文件打上了補(bǔ)丁而另一部分卻沒有,這樣一種不上不下的修訂狀態(tài)。所以總的來說,git apply
要比 patch
嚴(yán)謹(jǐn)許多。因?yàn)閮H僅是更新當(dāng)前的文件,所以此命令不會(huì)自動(dòng)生成提交對象,你得手工緩存相應(yīng)文件的更新狀態(tài)并執(zhí)行提交命令。
在實(shí)際打補(bǔ)丁之前,可以先用 git apply --check
查看補(bǔ)丁是否能夠干凈順利地應(yīng)用到當(dāng)前分支中:
$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
如果沒有任何輸出,表示我們可以順利采納該補(bǔ)丁。如果有問題,除了報(bào)告錯(cuò)誤信息之外,該命令還會(huì)返回一個(gè)非零的狀態(tài),所以在 shell 腳本里可用于檢測狀態(tài)。
如果貢獻(xiàn)者也用 Git,且擅于制作 format-patch
補(bǔ)丁,那你的合并工作將會(huì)非常輕松。因?yàn)檫@些補(bǔ)丁中除了文件內(nèi)容差異外,還包含了作者信息和提交消息。所以請鼓勵(lì)貢獻(xiàn)者用 format-patch
生成補(bǔ)丁。對于傳統(tǒng)的 diff
命令生成的補(bǔ)丁,則只能用 git apply
處理。
對于 format-patch
制作的新式補(bǔ)丁,應(yīng)當(dāng)使用 git am
命令。從技術(shù)上來說,git am
能夠讀取 mbox 格式的文件。這是種簡單的純文本文件,可以包含多封電郵,格式上用 From 加空格以及隨便什么輔助信息所組成的行作為分隔行,以區(qū)分每封郵件,就像這樣:
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function
Limit log functionality to the first 20
這是 format-patch
命令輸出的開頭幾行,也是一個(gè)有效的 mbox 文件格式。如果有人用 git send-email
給你發(fā)了一個(gè)補(bǔ)丁,你可以將此郵件下載到本地,然后運(yùn)行 git am
命令來應(yīng)用這個(gè)補(bǔ)丁。如果你的郵件客戶端能將多封電郵導(dǎo)出為 mbox 格式的文件,就可以用 git am
一次性應(yīng)用所有導(dǎo)出的補(bǔ)丁。
如果貢獻(xiàn)者將 format-patch
生成的補(bǔ)丁文件上傳到類似 Request Ticket 一樣的任務(wù)處理系統(tǒng),那么可以先下載到本地,繼而使用 git am
應(yīng)用該補(bǔ)?。?/p>
$ git am 0001-limit-log-function.patch
Applying: add limit to log function
你會(huì)看到它被干凈地應(yīng)用到本地分支,并自動(dòng)創(chuàng)建了新的提交對象。作者信息取自郵件頭 From
和 Date
,提交消息則取自 Subject
以及正文中補(bǔ)丁之前的內(nèi)容。來看具體實(shí)例,采納之前展示的那個(gè) mbox 電郵補(bǔ)丁后,最新的提交對象為:
$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Author: Jessica Smith <jessica@example.com>
AuthorDate: Sun Apr 6 10:17:23 2008 -0700
Commit: Scott Chacon <schacon@gmail.com>
CommitDate: Thu Apr 9 09:19:06 2009 -0700
add limit to log function
Limit log functionality to the first 20
Commit
部分顯示的是采納補(bǔ)丁的人,以及采納的時(shí)間。而 Author
部分則顯示的是原作者,以及創(chuàng)建補(bǔ)丁的時(shí)間。
有時(shí),我們也會(huì)遇到打不上補(bǔ)丁的情況。這多半是因?yàn)橹鞲煞种Ш脱a(bǔ)丁的基礎(chǔ)分支相差太遠(yuǎn),但也可能是因?yàn)槟承┮蕾囇a(bǔ)丁還未應(yīng)用。這種情況下,git am
會(huì)報(bào)錯(cuò)并詢問該怎么做:
$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".
Git 會(huì)在有沖突的文件里加入沖突解決標(biāo)記,這同合并或衍合操作一樣。解決的辦法也一樣,先編輯文件消除沖突,然后暫存文件,最后運(yùn)行 git am --resolved
提交修正結(jié)果:
$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: seeing if this helps the gem
如果想讓 Git 更智能地處理沖突,可以用 -3
選項(xiàng)進(jìn)行三方合并。如果當(dāng)前分支未包含該補(bǔ)丁的基礎(chǔ)代碼或其祖先,那么三方合并就會(huì)失敗,所以該選項(xiàng)默認(rèn)為關(guān)閉狀態(tài)。一般來說,如果該補(bǔ)丁是基于某個(gè)公開的提交制作而成的話,你總是可以通過同步來獲取這個(gè)共同祖先,所以用三方合并選項(xiàng)可以解決很多麻煩:
$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
像上面的例子,對于打過的補(bǔ)丁我又再打一遍,自然會(huì)產(chǎn)生沖突,但因?yàn)榧由狭?nbsp;-3
選項(xiàng),所以它很聰明地告訴我,無需更新,原有的補(bǔ)丁已經(jīng)應(yīng)用。
對于一次應(yīng)用多個(gè)補(bǔ)丁時(shí)所用的 mbox 格式文件,可以用 am
命令的交互模式選項(xiàng) -i
,這樣就會(huì)在打每個(gè)補(bǔ)丁前停住,詢問該如何操作:
$ git am -3 -i mbox
Commit Body is:
--------------------------
seeing if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all
在多個(gè)補(bǔ)丁要打的情況下,這是個(gè)非常好的辦法,一方面可以預(yù)覽下補(bǔ)丁內(nèi)容,同時(shí)也可以有選擇性的接納或跳過某些補(bǔ)丁。
打完所有補(bǔ)丁后,如果測試下來新特性可以正常工作,那就可以安心地將當(dāng)前特性分支合并到長期分支中去了。
如果貢獻(xiàn)者有自己的 Git 倉庫,并將修改推送到此倉庫中,那么當(dāng)你拿到倉庫的訪問地址和對應(yīng)分支的名稱后,就可以加為遠(yuǎn)程分支,然后在本地進(jìn)行合并。
比如,Jessica 發(fā)來一封郵件,說在她代碼庫中的 ruby-client
分支上已經(jīng)實(shí)現(xiàn)了某個(gè)非常棒的新功能,希望我們能幫忙測試一下。我們可以先把她的倉庫加為遠(yuǎn)程倉庫,然后抓取數(shù)據(jù),完了再將她所說的分支檢出到本地來測試:
$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client
若是不久她又發(fā)來郵件,說還有個(gè)很棒的功能實(shí)現(xiàn)在另一分支上,那我們只需重新抓取下最新數(shù)據(jù),然后檢出那個(gè)分支到本地就可以了,無需重復(fù)設(shè)置遠(yuǎn)程倉庫。
這種做法便于同別人保持長期的合作關(guān)系。但前提是要求貢獻(xiàn)者有自己的服務(wù)器,而我們也需要為每個(gè)人建一個(gè)遠(yuǎn)程分支。有些貢獻(xiàn)者提交代碼補(bǔ)丁并不是很頻繁,所以通過郵件接收補(bǔ)丁效率會(huì)更高。同時(shí)我們自己也不會(huì)希望建上百來個(gè)分支,卻只從每個(gè)分支取一兩個(gè)補(bǔ)丁。但若是用腳本程序來管理,或直接使用代碼倉庫托管服務(wù),就可以簡化此過程。當(dāng)然,選擇何種方式取決于你和貢獻(xiàn)者的喜好。
使用遠(yuǎn)程分支的另外一個(gè)好處是能夠得到提交歷史。不管代碼合并是不是會(huì)有問題,至少我們知道該分支的歷史分叉點(diǎn),所以默認(rèn)會(huì)從共同祖先開始自動(dòng)進(jìn)行三方合并,無需 -3
選項(xiàng),也不用像打補(bǔ)丁那樣祈禱存在共同的基準(zhǔn)點(diǎn)。
如果只是臨時(shí)合作,只需用 git pull
命令抓取遠(yuǎn)程倉庫上的數(shù)據(jù),合并到本地臨時(shí)分支就可以了。一次性的抓取動(dòng)作自然不會(huì)把該倉庫地址加為遠(yuǎn)程倉庫。
$ git pull git://github.com/onetimeguy/project.git
From git://github.com/onetimeguy/project
* branch HEAD -> FETCH_HEAD
Merge made by recursive.
現(xiàn)在特性分支上已合并好了貢獻(xiàn)者的代碼,是時(shí)候決斷取舍了。本節(jié)將回顧一些之前學(xué)過的命令,以看清將要合并到主干的是哪些代碼,從而理解它們到底做了些什么,是否真的要并入。
一般我們會(huì)先看下,特性分支上都有哪些新增的提交。比如在 contrib
特性分支上打了兩個(gè)補(bǔ)丁,僅查看這兩個(gè)補(bǔ)丁的提交信息,可以用 --not
選項(xiàng)指定要屏蔽的分支 master
,這樣就會(huì)剔除重復(fù)的提交歷史:
$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Oct 24 09:53:59 2008 -0700
seeing if this helps the gem
commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Oct 22 19:38:36 2008 -0700
updated the gemspec to hopefully work better
還可以查看每次提交的具體修改。請牢記,在 git log
后加 -p
選項(xiàng)將展示每次提交的內(nèi)容差異。
如果想看當(dāng)前分支同其他分支合并時(shí)的完整內(nèi)容差異,有個(gè)小竅門:
$ git diff master
雖然能得到差異內(nèi)容,但請記住,結(jié)果有可能和我們的預(yù)期不同。一旦主干 master
在特性分支創(chuàng)建之后有所修改,那么通過 diff
命令來比較的,是最新主干上的提交快照。顯然,這不是我們所要的。比方在 master
分支中某個(gè)文件里添了一行,然后運(yùn)行上面的命令,簡單的比較最新快照所得到的結(jié)論只能是,特性分支中刪除了這一行。
這個(gè)很好理解:如果 master
是特性分支的直接祖先,不會(huì)產(chǎn)生任何問題;如果它們的提交歷史在不同的分叉上,那么產(chǎn)生的內(nèi)容差異,看起來就像是增加了特性分支上的新代碼,同時(shí)刪除了 master
分支上的新代碼。
實(shí)際上我們真正想要看的,是新加入到特性分支的代碼,也就是合并時(shí)會(huì)并入主干的代碼。所以,準(zhǔn)確地講,我們應(yīng)該比較特性分支和它同 master
分支的共同祖先之間的差異。
我們可以手工定位它們的共同祖先,然后與之比較:
$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db
但這么做很麻煩,所以 Git 提供了便捷的 ...
語法。對于 diff
命令,可以把 ...
加在原始分支(擁有共同祖先)和當(dāng)前分支之間:
$ git diff master...contrib
現(xiàn)在看到的,就是實(shí)際將要引入的新代碼。這是一個(gè)非常有用的命令,應(yīng)該牢記。
一旦特性分支準(zhǔn)備停當(dāng),接下來的問題就是如何集成到更靠近主線的分支中。此外還要考慮維護(hù)項(xiàng)目的總體步驟是什么。雖然有很多選擇,不過我們這里只介紹其中一部分。
一般最簡單的情形,是在 master
分支中維護(hù)穩(wěn)定代碼,然后在特性分支上開發(fā)新功能,或是審核測試別人貢獻(xiàn)的代碼,接著將它并入主干,最后刪除這個(gè)特性分支,如此反復(fù)。來看示例,假設(shè)當(dāng)前代碼庫中有兩個(gè)分支,分別為 ruby_client
和 php_client
,如圖 5-19 所示。然后先把 ruby_client
合并進(jìn)主干,再合并 php_client
,最后的提交歷史如圖 5-20 所示。
圖 5-19. 多個(gè)特性分支
圖 5-20. 合并特性分支之后
這是最簡單的流程,所以在處理大一些的項(xiàng)目時(shí)可能會(huì)有問題。
對于大型項(xiàng)目,至少需要維護(hù)兩個(gè)長期分支 master
和 develop
。新代碼(圖 5-21 中的 ruby_client
)將首先并入 develop
分支(圖 5-22 中的 C8
),經(jīng)過一個(gè)階段,確認(rèn) develop
中的代碼已穩(wěn)定到可發(fā)行時(shí),再將 master
分支快進(jìn)到穩(wěn)定點(diǎn)(圖 5-23 中的 C8
)。而平時(shí)這兩個(gè)分支都會(huì)被推送到公開的代碼庫。
圖 5-21. 特性分支合并前
圖 5-22. 特性分支合并后
圖 5-23. 特性分支發(fā)布后
這樣,在人們克隆倉庫時(shí)就有兩種選擇:既可檢出最新穩(wěn)定版本,確保正常使用;也能檢出開發(fā)版本,試用最前沿的新特性。 你也可以擴(kuò)展這個(gè)概念,先將所有新代碼合并到臨時(shí)特性分支,等到該分支穩(wěn)定下來并通過測試后,再并入 develop
分支。然后,讓時(shí)間檢驗(yàn)一切,如果這些代碼確實(shí)可以正常工作相當(dāng)長一段時(shí)間,那就有理由相信它已經(jīng)足夠穩(wěn)定,可以放心并入主干分支發(fā)布。
Git 項(xiàng)目本身有四個(gè)長期分支:用于發(fā)布的 master
分支、用于合并基本穩(wěn)定特性的 next
分支、用于合并仍需改進(jìn)特性的 pu
分支(pu 是 proposed updates 的縮寫),以及用于除錯(cuò)維護(hù)的 maint
分支(maint 取自 maintenance)。維護(hù)者可以按照之前介紹的方法,將貢獻(xiàn)者的代碼引入為不同的特性分支(如圖 5-24 所示),然后測試評估,看哪些特性能穩(wěn)定工作,哪些還需改進(jìn)。穩(wěn)定的特性可以并入 next
分支,然后再推送到公共倉庫,以供其他人試用。
圖 5-24. 管理復(fù)雜的并行貢獻(xiàn)
仍需改進(jìn)的特性可以先并入 pu
分支。直到它們完全穩(wěn)定后再并入 master
。同時(shí)一并檢查下 next
分支,將足夠穩(wěn)定的特性也并入 master
。所以一般來說,master
始終是在快進(jìn),next
偶爾做下衍合,而 pu
則是頻繁衍合,如圖 5-25 所示:
圖 5-25. 將特性并入長期分支
并入 master
后的特性分支,已經(jīng)無需保留分支索引,放心刪除好了。Git 項(xiàng)目還有一個(gè) maint
分支,它是以最近一次發(fā)行版為基礎(chǔ)分化而來的,用于維護(hù)除錯(cuò)補(bǔ)丁。所以克隆 Git 項(xiàng)目倉庫后會(huì)得到這四個(gè)分支,通過檢出不同分支可以了解各自進(jìn)展,或是試用前沿特性,或是貢獻(xiàn)代碼。而維護(hù)者則通過管理這些分支,逐步有序地并入第三方貢獻(xiàn)。
一些維護(hù)者更喜歡衍合或者挑揀貢獻(xiàn)者的代碼,而不是簡單的合并,因?yàn)檫@樣能夠保持線性的提交歷史。如果你完成了一個(gè)特性的開發(fā),并決定將它引入到主干代碼中,你可以轉(zhuǎn)到那個(gè)特性分支然后執(zhí)行衍合命令,好在你的主干分支上(也可能是develop
分支之類的)重新提交這些修改。如果這些代碼工作得很好,你就可以快進(jìn)master
分支,得到一個(gè)線性的提交歷史。
另一個(gè)引入代碼的方法是挑揀。挑揀類似于針對某次特定提交的衍合。它首先提取某次提交的補(bǔ)丁,然后試著應(yīng)用在當(dāng)前分支上。如果某個(gè)特性分支上有多個(gè)commits,但你只想引入其中之一就可以使用這種方法。也可能僅僅是因?yàn)槟阆矚g用挑揀,討厭衍合。假設(shè)你有一個(gè)類似圖 5-26 的工程。
圖 5-26. 挑揀(cherry-pick)之前的歷史
如果你希望拉取e43a6
到你的主干分支,可以這樣:
$ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
3 files changed, 17 insertions(+), 3 deletions(-)
這將會(huì)引入e43a6
的代碼,但是會(huì)得到不同的SHA-1值,因?yàn)閼?yīng)用日期不同。現(xiàn)在你的歷史看起來像圖 5-27.
圖 5-27. 挑揀(cherry-pick)之后的歷史
現(xiàn)在,你可以刪除這個(gè)特性分支并丟棄你不想引入的那些commit。
你可以刪除上次發(fā)布的版本并重新打標(biāo)簽,也可以像第二章所說的那樣建立一個(gè)新的標(biāo)簽。如果你決定以維護(hù)者的身份給發(fā)行版簽名,應(yīng)該這樣做:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gmail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
完成簽名之后,如何分發(fā)PGP公鑰(public key)是個(gè)問題。(譯者注:分發(fā)公鑰是為了驗(yàn)證標(biāo)簽)。還好,Git的設(shè)計(jì)者想到了解決辦法:可以把key(既公鑰)作為blob變量寫入Git庫,然后把它的內(nèi)容直接寫在標(biāo)簽里。gpg --list-keys
命令可以顯示出你所擁有的key:
$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub 1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid Scott Chacon <schacon@gmail.com>
sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09]
然后,導(dǎo)出key的內(nèi)容并經(jīng)由管道符傳遞給git hash-object
,之后鑰匙會(huì)以blob類型寫入Git中,最后返回這個(gè)blob量的SHA-1值:
$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92
現(xiàn)在你的Git已經(jīng)包含了這個(gè)key的內(nèi)容了,可以通過不同的SHA-1值指定不同的key來創(chuàng)建標(biāo)簽。
$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92
在運(yùn)行git push --tags
命令之后,maintainer-pgp-pub
標(biāo)簽就會(huì)公布給所有人。如果有人想要校驗(yàn)標(biāo)簽,他可以使用如下命令導(dǎo)入你的key:
$ git show maintainer-pgp-pub | gpg --import
人們可以用這個(gè)key校驗(yàn)?zāi)愫灻乃袠?biāo)簽。另外,你也可以在標(biāo)簽信息里寫入一個(gè)操作向?qū)В脩糁恍枰\(yùn)行git show <tag>
查看標(biāo)簽信息,然后按照你的向?qū)Ь湍芡瓿尚r?yàn)。
因?yàn)镚it不會(huì)為每次提交自動(dòng)附加類似'v123'的遞增序列,所以如果你想要得到一個(gè)便于理解的提交號可以運(yùn)行git describe
命令。Git將會(huì)返回一個(gè)字符串,由三部分組成:最近一次標(biāo)定的版本號,加上自那次標(biāo)定之后的提交次數(shù),再加上一段所描述的提交的SHA-1值:
$ git describe master
v1.6.2-rc1-20-g8c5b85c
這個(gè)字符串可以作為快照的名字,方便人們理解。如果你的Git是你自己下載源碼然后編譯安裝的,你會(huì)發(fā)現(xiàn)git --version
命令的輸出和這個(gè)字符串差不多。如果在一個(gè)剛剛打完標(biāo)簽的提交上運(yùn)行describe
命令,只會(huì)得到這次標(biāo)定的版本號,而沒有后面兩項(xiàng)信息。
git describe
命令只適用于有標(biāo)注的標(biāo)簽(通過-a
或者-s
選項(xiàng)創(chuàng)建的標(biāo)簽),所以發(fā)行版的標(biāo)簽都應(yīng)該是帶有標(biāo)注的,以保證git describe
能夠正確的執(zhí)行。你也可以把這個(gè)字符串作為checkout
或者show
命令的目標(biāo),因?yàn)樗麄冏罱K都依賴于一個(gè)簡短的SHA-1值,當(dāng)然如果這個(gè)SHA-1值失效他們也跟著失效。最近Linux內(nèi)核為了保證SHA-1值的唯一性,將位數(shù)由8位擴(kuò)展到10位,這就導(dǎo)致擴(kuò)展之前的git describe
輸出完全失效了。
現(xiàn)在可以發(fā)布一個(gè)新的版本了。首先要將代碼的壓縮包歸檔,方便那些可憐的還沒有使用Git的人們??梢允褂?code>git archive:
$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz
這個(gè)壓縮包解壓出來的是一個(gè)文件夾,里面是你項(xiàng)目的最新代碼快照。你也可以用類似的方法建立一個(gè)zip壓縮包,在git archive
加上--format=zip
選項(xiàng):
$ git archive master --prefix='project/' --format=zip > `git describe master`.zip
現(xiàn)在你有了一個(gè)tar.gz壓縮包和一個(gè)zip壓縮包,可以把他們上傳到你網(wǎng)站上或者用e-mail發(fā)給別人。
是時(shí)候通知郵件列表里的朋友們來檢驗(yàn)?zāi)愕某晒?。使?code>git shortlog命令可以方便快捷的制作一份修改日志(changelog),告訴大家上次發(fā)布之后又增加了哪些特性和修復(fù)了哪些bug。實(shí)際上這個(gè)命令能夠統(tǒng)計(jì)給定范圍內(nèi)的所有提交;假如你上一次發(fā)布的版本是v1.0.1,下面的命令將給出自從上次發(fā)布之后的所有提交的簡介:
$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (8):
Add support for annotated tags to Grit::Tag
Add packed-refs annotated tag support.
Add Grit::Commit#to_patch
Update version and History.txt
Remove stray `puts`
Make ls_tree ignore nils
Tom Preston-Werner (4):
fix dates in history
dynamic version method
Version bump to 1.0.2
Regenerated gemspec for version 1.0.2
這就是自從v1.0.1版本以來的所有提交的簡介,內(nèi)容按照作者分組,以便你能快速的發(fā)e-mail給他們。
更多建議: