http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-1.png" alt="images/git-workflows-forking-1" />
和任何使用 Git
項(xiàng)目一樣,第一步是創(chuàng)建在服務(wù)器上一個(gè)正式倉(cāng)庫(kù),讓所有團(tuán)隊(duì)成員都可以訪問到。
通常這個(gè)倉(cāng)庫(kù)也會(huì)作為項(xiàng)目維護(hù)者的公開倉(cāng)庫(kù)。
公開倉(cāng)庫(kù)應(yīng)該是裸倉(cāng)庫(kù),不管是不是正式代碼庫(kù)。
所以項(xiàng)目維護(hù)者會(huì)運(yùn)行像下面的命令來搭建正式倉(cāng)庫(kù):
ssh user@host
git init --bare /path/to/repo.git
Bitbucket
和 Stash
提供了一個(gè)方便的 GUI
客戶端以完成上面命令行做的事。
這個(gè)搭建中央倉(cāng)庫(kù)的過程和前面提到的工作流完全一樣。
如果有現(xiàn)存的代碼庫(kù),維護(hù)者也要 push
到這個(gè)倉(cāng)庫(kù)中。
fork
正式倉(cāng)庫(kù)http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-2.png" alt="git-workflows-forking-2" />
其它所有的開發(fā)需要 fork
正式倉(cāng)庫(kù)。
可以用 git clone
命令用 SSH
協(xié)議連通到服務(wù)器,
拷貝倉(cāng)庫(kù)到服務(wù)器另一個(gè)位置 —— 是的,fork
操作基本上就只是一個(gè)服務(wù)端的克隆。
Bitbucket
和 Stash
上可以點(diǎn)一下按鈕就讓開發(fā)者完成倉(cāng)庫(kù)的 fork
操作。
這一步完成后,每個(gè)開發(fā)都在服務(wù)端有一個(gè)自己的倉(cāng)庫(kù)。和正式倉(cāng)庫(kù)一樣,這些倉(cāng)庫(kù)應(yīng)該是裸倉(cāng)庫(kù)。
fork
出來的倉(cāng)庫(kù)http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-3.png" alt="git-workflows-forking-3" />
下一步,各個(gè)開發(fā)者要克隆自己的公開倉(cāng)庫(kù),用熟悉的 git clone
命令。
在這個(gè)示例中,假定用 Bitbucket
托管了倉(cāng)庫(kù)。記住,如果這樣的話各個(gè)開發(fā)者需要有各自的 Bitbucket
賬號(hào),
使用下面命令克隆服務(wù)端自己的倉(cāng)庫(kù):
git clone https://user@bitbucket.org/user/repo.git
相比前面介紹的工作流只用了一個(gè) origin
遠(yuǎn)程別名指向中央倉(cāng)庫(kù), Forking
工作流需要2個(gè)遠(yuǎn)程別名 ——
一個(gè)指向正式倉(cāng)庫(kù),另一個(gè)指向開發(fā)者自己的服務(wù)端倉(cāng)庫(kù)。別名的名字可以任意命名,常見的約定是使用 origin
作為遠(yuǎn)程克隆的倉(cāng)庫(kù)的別名
(這個(gè)別名會(huì)在運(yùn)行 git clone
自動(dòng)創(chuàng)建),upstream
(上游)作為正式倉(cāng)庫(kù)的別名。
git remote add upstream https://bitbucket.org/maintainer/repo
需要自己用上面的命令創(chuàng)建 upstream
別名。這樣可以簡(jiǎn)單地保持本地倉(cāng)庫(kù)和正式倉(cāng)庫(kù)的同步更新。
注意,如果上游倉(cāng)庫(kù)需要認(rèn)證(比如不是開源的),你需要提供用戶:
git remote add upstream https://user@bitbucket.org/maintainer/repo.git
這時(shí)在克隆和 pull
正式倉(cāng)庫(kù)時(shí),需要提供用戶的密碼。
http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-4.png" alt="git-workflows-forking-4" />
在剛克隆的本地倉(cāng)庫(kù)中,開發(fā)者可以像其它工作流一樣的編輯代碼、提交修改和新建分支:
git checkout -b some-feature
# Edit some code
git commit -a -m "Add first draft of some feature"
所有的修改都是私有的直到 push
到自己公開倉(cāng)庫(kù)中。如果正式項(xiàng)目已經(jīng)往前走了,可以用 git pull
命令獲得新的提交:
git pull upstream master
由于開發(fā)者應(yīng)該都在專門的功能分支上工作,pull
操作結(jié)果會(huì)都是快進(jìn)合并。
http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-5.png" alt="git-workflows-forking-5" />
一旦開發(fā)者準(zhǔn)備好了分享新功能,需要做二件事。
首先,通過 push
他的貢獻(xiàn)代碼到自己的公開倉(cāng)庫(kù)中,讓其它的開發(fā)者都可以訪問到。
他的 origin
遠(yuǎn)程別名應(yīng)該已經(jīng)有了,所以要做的就是:
git push origin feature-branch
這里和之前的工作流的差異是,origin
遠(yuǎn)程別名指向開發(fā)者自己的服務(wù)端倉(cāng)庫(kù),而不是正式倉(cāng)庫(kù)。
第二件事,開發(fā)者要通知項(xiàng)目維護(hù)者,想要合并他的新功能到正式庫(kù)中。
Bitbucket
和 Stash
提供了 Pull Request
按鈕,彈出表單讓你指定哪個(gè)分支要合并到正式倉(cāng)庫(kù)。
一般你會(huì)想集成你的功能分支到上游遠(yuǎn)程倉(cāng)庫(kù)的 master
分支中。
http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-6.png" alt="git-workflows-forking-6" />
當(dāng)項(xiàng)目維護(hù)者收到 pull request
,他要做的是決定是否集成它到正式代碼庫(kù)中。有二種方式來做:
pull request
中查看代碼pull
代碼到他自己的本地倉(cāng)庫(kù),再手動(dòng)合并第一種做法更簡(jiǎn)單,維護(hù)者可以在 GUI
中查看變更的差異,做評(píng)注和執(zhí)行合并。
但如果出現(xiàn)了合并沖突,需要第二種做法來解決。這種情況下,維護(hù)者需要從開發(fā)者的服務(wù)端倉(cāng)庫(kù)中 fetch
功能分支,合并到他本地的 master
分支,解決沖突:
git fetch https://bitbucket.org/user/repo feature-branch
# 查看變更
git checkout master
git merge FETCH_HEAD
變更集成到本地的 master
分支后,維護(hù)者要 push
變更到服務(wù)器上的正式倉(cāng)庫(kù),這樣其它的開發(fā)者都能訪問到:
git push origin master
注意,維護(hù)者的 origin
是指向他自己公開倉(cāng)庫(kù)的,即是項(xiàng)目的正式代碼庫(kù)。到此,開發(fā)者的貢獻(xiàn)完全集成到了項(xiàng)目中。
http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflows-forking-7.png" alt="git-workflows-forking-7" />
由于正式代碼庫(kù)往前走了,其它的開發(fā)需要和正式倉(cāng)庫(kù)做同步:
git pull upstream master
如果你之前是使用 SVN
,Forking
工作流可能看起來像是一個(gè)激進(jìn)的范式切換( paradigm shift )。
但不要害怕,這個(gè)工作流實(shí)際上就是在功能分支工作流之上引入另一個(gè)抽象層。
不是直接通過單個(gè)中央倉(cāng)庫(kù)來分享分支,而是把貢獻(xiàn)代碼發(fā)布到開發(fā)者自己的服務(wù)端倉(cāng)庫(kù)中。
示例中解釋了,一個(gè)貢獻(xiàn)如何從一個(gè)開發(fā)者流到正式的 master
分支中,但同樣的方法可以把貢獻(xiàn)集成到任一個(gè)倉(cāng)庫(kù)中。
比如,如果團(tuán)隊(duì)的幾個(gè)人協(xié)作實(shí)現(xiàn)一個(gè)功能,可以在開發(fā)之間用相同的方法分享變更,完全不涉及正式倉(cāng)庫(kù)。
這使得 Forking
工作流對(duì)于松散組織的團(tuán)隊(duì)來說是個(gè)非常強(qiáng)大的工具。任一開發(fā)者可以方便地和另一開發(fā)者分享變更,任何分支都能有效地合并到正式代碼庫(kù)中。