描述如何向一個項(xiàng)目貢獻(xiàn)的主要困難在于完成貢獻(xiàn)有很多不同的方式。因?yàn)?Git 非常靈活,人們可以通過不同的方式來一起工作,所以描述應(yīng)該如何貢獻(xiàn)并不是非常準(zhǔn)確 - 每一個項(xiàng)目都有一點(diǎn)兒不同。影響因素包括活躍貢獻(xiàn)者的數(shù)量、選擇的工作流程、提交權(quán)限與可能包含的外部貢獻(xiàn)方法。
第一個影響因素是活躍貢獻(xiàn)者的數(shù)量 - 積極地向這個項(xiàng)目貢獻(xiàn)代碼的用戶數(shù)量以及他們的貢獻(xiàn)頻率。在許多情況下,你可能會有兩三個開發(fā)者一天提交幾次,對于不活躍的項(xiàng)目可能更少。對于大一些的公司或項(xiàng)目,開發(fā)者的數(shù)量可能會是上千,每天都有成百上千次提交。這很重要,因?yàn)殡S著開發(fā)者越來越多,在確保你的代碼能干凈地應(yīng)用或輕松地合并時會遇到更多問題。提交的改動可能表現(xiàn)為過時的,也可能在你正在做改動或者等待改動被批準(zhǔn)應(yīng)用時被合并入的工作嚴(yán)重?fù)p壞。如何保證代碼始終是最新的,并且提交始終是有效的?
下一個影響因素是項(xiàng)目使用的工作流程。它是中心化的嗎,即每一個開發(fā)者都對主線代碼有相同的寫入權(quán)限?項(xiàng)目是否有一個檢查所有補(bǔ)丁的維護(hù)者或整合者?是否所有的補(bǔ)丁是同行評審后批準(zhǔn)的?你是否參與了那個過程?是否存在副官系統(tǒng),你必須先將你的工作提交到上面?
下一個問題是提交權(quán)限。是否有項(xiàng)目的寫權(quán)限會使向項(xiàng)目貢獻(xiàn)所需的流程有極大的不同。如果沒有寫權(quán)限,項(xiàng)目會選擇何種方式接受貢獻(xiàn)的工作?是否甚至有一個如何貢獻(xiàn)的規(guī)范?你一次貢獻(xiàn)多少工作?你多久貢獻(xiàn)一次?
所有這些問題都會影響實(shí)際如何向一個項(xiàng)目貢獻(xiàn),以及對你來說哪些工作流程更適合或者可用。我們將會由淺入深,通過一系列用例來講述其中的每一個方面;從這些例子應(yīng)該能夠建立實(shí)際中你需要的特定工作流程。
在我們開始查看特定的用例前,這里有一個關(guān)于提交信息的快速說明。有一個好的創(chuàng)建提交的準(zhǔn)則并且堅(jiān)持使用會讓與 Git 工作和與其他人協(xié)作更容易。Git 項(xiàng)目提供了一個文檔,其中列舉了關(guān)于創(chuàng)建提交到提交補(bǔ)丁的若干好的提示 - 可以在 Git 源代碼中的 Documentation/SubmittingPatches
文件中閱讀它。
首先,你不會想要把空白錯誤(根據(jù) git help diff 的描述,結(jié)合下面給出的圖片,空白錯誤是指行尾的空格、Tab 制表符,和行首空格后跟 Tab 制表符的行為)提交上去。Git 提供了一個簡單的方式來檢查這點(diǎn) - 在提交前,運(yùn)行 git diff --check
,它將會找到可能的空白錯誤并將它們?yōu)槟懔谐鰜怼?/p>
“提交區(qū)間” 中詳細(xì)介紹這個語法。
目前,我們可以從輸出中看到有一個 John 生成的但是 Jessica 還沒有合并入的提交。如果她合并 origin/master
,也就是說將會修改她的本地工作的那個單個提交。
現(xiàn)在,Jessica 可以合并她的特性工作到她的 master 分支,合并 John 的工作(origin/master
)進(jìn)入她的 master
分支,然后再次推送回服務(wù)器。首先,為了整合所有這些工作她切換回她的 master 分支。
$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
她既可以先合并 origin/master
也可以先合并 issue54
- 它們都是上游,所以順序并沒有關(guān)系。不論她選擇的順序是什么最終的結(jié)果快照是完全一樣的;只是歷史會有一點(diǎn)輕微的區(qū)別。她選擇先合并入 issue54
:
$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
README | 1 +
lib/simplegit.rb | 6 +++++-
2 files changed, 6 insertions(+), 1 deletions(-)
沒有發(fā)生問題;如你所見它是一次簡單的快進(jìn)?,F(xiàn)在 Jessica 合并入 John 的工作(origin/master
):
$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by recursive.
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
每一個文件都干凈地合并了,Jessica 的歷史看起來像這樣:
Figure 5-11. 推送所有的改動回服務(wù)器后 Jessica 的歷史
這是一個最簡單的工作流程。你通常在一個特性分支工作一會兒,當(dāng)它準(zhǔn)備好整合時合并回你的 master 分支。當(dāng)想要共享工作時,將其合并回你自己的 master 分支,如果有改動的話然后抓取并合并 origin/master
,最終推送到服務(wù)器上的 master
分支。通常順序像這樣:
Figure 5-13. Jessica 的初始提交歷史
她準(zhǔn)備好推送工作了,但是一封來自 Josie 的郵件告知一些初始工作已經(jīng)被推送到服務(wù)器上的 featureBee
上了。Jessica 在能推送到服務(wù)器前首先需要將那些改動與她自己的合并。然后她可以通過 git fetch
抓取 Josie 的改動:
$ git fetch origin
...
From jessica@githost:simplegit
* [new branch] featureBee -> origin/featureBee
Jessica 現(xiàn)在可以通過 git merge
將其合并到她做的工作中:
$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by recursive.
lib/simplegit.rb | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
有點(diǎn)兒問題 - 她需要將在 featureB
分支上合并的工作推送到服務(wù)器上的 featureBee
分支。她可以通過指定本地分支加上冒號(:)加上遠(yuǎn)程分支給 git push
命令來這樣做:
$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
fba9af8..cd685d1 featureB -> featureBee
這稱作一個 引用規(guī)格。查看 “引用規(guī)格” 了解關(guān)于 Git 引用規(guī)格與通過它們可以做的不同的事情的詳細(xì)討論。也要注意 -u
標(biāo)記;這是 --set-upstream
的簡寫,該標(biāo)記會為之后輕松地推送與拉取配置分支。
緊接著,John 發(fā)郵件給 Jessica 說他已經(jīng)推送了一些改動到 featureA
分支并要求她去驗(yàn)證它們。她運(yùn)行一個 git fetch
來拉取下那些改動:
$ git fetch origin
...
From jessica@githost:simplegit
3300904..aad881d featureA -> origin/featureA
然后,通過 git log
她可以看到哪些發(fā)生了改變:
$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date: Fri May 29 19:57:33 2009 -0700
changed log output to 30 from 25
最終,她合并 John 的工作到她自己的 featureA
分支:
$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Jessica 想要輕微調(diào)整一些東西,所以她再次提交然后將其推送回服務(wù)器:
$ git commit -am 'small tweak'
[featureA 774b3ed] small tweak
1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
3300904..774b3ed featureA -> featureA
Jessica 的提交歷史現(xiàn)在看起來像這樣:
Figure 5-15. 合并了 Jessica 的兩個特性分支后她的歷史
許多團(tuán)隊(duì)切換到 Git 是因?yàn)檫@一允許多個團(tuán)隊(duì)并行工作、并在之后合并不同工作的能力。團(tuán)隊(duì)中更小一些的子小組可以通過遠(yuǎn)程分支協(xié)作而不必影響或妨礙整個團(tuán)隊(duì)的能力是 Git 的一個巨大優(yōu)勢。在這兒看到的工作流程順序類似這樣:
Figure?5-18
Figure 5-19. featureBv2
工作之后的提交歷史
許多項(xiàng)目建立了接受補(bǔ)丁的流程 - 需要檢查每一個項(xiàng)目的特定規(guī)則,因?yàn)樗鼈冎g有區(qū)別。因?yàn)橛袔讉€歷史悠久的、大型的項(xiàng)目會通過一個開發(fā)者的郵件列表接受補(bǔ)丁,現(xiàn)在我們將會通過一個例子來演示。
工作流程與之前的用例是類似的 - 你為工作的每一個補(bǔ)丁序列創(chuàng)建特性分支。區(qū)別是如何提交它們到項(xiàng)目中。生成每一個提交序列的電子郵件版本然后郵寄它們到開發(fā)者郵件列表,而不是派生項(xiàng)目然后推送到你自己的可寫版本。
$ git checkout -b topicA
# (work)
$ git commit
# (work)
$ git commit
現(xiàn)在有兩個提交要發(fā)送到郵件列表。使用 git format-patch
來生成可以郵寄到列表的 mbox 格式的文件 - 它將每一個提交轉(zhuǎn)換為一封電子郵件,提交信息的第一行作為主題,剩余信息與提交引入的補(bǔ)丁作為正文。它有一個好處是是使用 format-patch
生成的一封電子郵件應(yīng)用的提交正確地保留了所有的提交信息。
$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
format-patch
命令打印出它創(chuàng)建的補(bǔ)丁文件名字。-M
開關(guān)告訴 Git 查找重命名。文件最后看起來像這樣:
$ cat 0001-add-limit-to-log-function.patch
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
---
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log #{treeish}")
+ command("git log -n 20 #{treeish}")
end
def ls_tree(treeish = 'master')
--
2.1.0
也可以編輯這些補(bǔ)丁文件為郵件列表添加更多不想要在提交信息中顯示出來的信息。如果在 ---
行與補(bǔ)丁開頭(diff --git
行)之間添加文本,那么開發(fā)者就可以閱讀它;但是應(yīng)用補(bǔ)丁時會排除它。
為了將其郵寄到郵件列表,你既可以將文件粘貼進(jìn)電子郵件客戶端,也可以通過命令行程序發(fā)送它。粘貼文本經(jīng)常會發(fā)生格式化問題,特別是那些不會合適地保留換行符與其他空白的 “更聰明的” 客戶端。幸運(yùn)的是,Git 提供了一個工具幫助你通過 IMAP 發(fā)送正確格式化的補(bǔ)丁,這可能對你更容易些。我們將會演示如何通過 Gmail 發(fā)送一個補(bǔ)丁,它正好是我們所知最好的郵件代理;可以在之前提到的 Git 源代碼中的 Documentation/SubmittingPatches
文件的最下面了解一系列郵件程序的詳細(xì)指令。
首先,需要在 ~/.gitconfig
文件中設(shè)置 imap 區(qū)塊??梢酝ㄟ^一系列的 git config
命令來分別設(shè)置每一個值,或者手動添加它們,不管怎樣最后配置文件應(yīng)該看起來像這樣:
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = user@gmail.com
pass = p4ssw0rd
port = 993
sslverify = false
如果 IMAP 服務(wù)器不使用 SSL,最后兩行可能沒有必要,host 的值會是 imap://
而不是 imaps://
。當(dāng)那些設(shè)置完成后,可以使用 git imap-send
將補(bǔ)丁序列放在特定 IMAP 服務(wù)器的 Drafts 文件夾中:
$ cat *.patch |git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done
在這個時候,你應(yīng)該能夠到 Drafts 文件夾中,修改收件人字段為想要發(fā)送補(bǔ)丁的郵件列表,可能需要抄送給維護(hù)者或負(fù)責(zé)那個部分的人,然后發(fā)送。
你也可以通過一個 SMTP 服務(wù)器發(fā)送補(bǔ)丁。同之前一樣,你可以通過一系列的 git config
命令來分別設(shè)置選項(xiàng),或者你可以手動地將它們添加到你的 ~/.gitconfig
文件的 sendmail 區(qū)塊:
[sendemail]
smtpencryption = tls
smtpserver = smtp.gmail.com
smtpuser = user@gmail.com
smtpserverport = 587
當(dāng)這完成后,你可以使用 git send-email
發(fā)送你的補(bǔ)?。?/p>
$ git send-email *.patch
0001-added-limit-to-log-function.patch
0002-changed-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y
然后,對于正在發(fā)送的每一個補(bǔ)丁,Git 會吐出這樣的一串日志信息:
(mbox) Adding cc: Jessica Smith <jessica@example.com> from
\line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] added limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>
Result: OK
這個部分介紹了處理可能會遇到的幾個迥然不同類型的 Git 項(xiàng)目的一些常見的工作流程,介紹了幫助管理這個過程的一些新工具。接下來,你會了解到如何在貢獻(xiàn)的另一面工作:維護(hù)一個 Git 項(xiàng)目。你將會學(xué)習(xí)如何成為一個仁慈的獨(dú)裁者或整合管理者。
更多建議: