鍍金池/ 教程/ Java/ 示例
功能分支工作流
工作方式
正式倉庫
示例
前言
<code>Gitflow</code> 工作流
工作流概要
<code>Forking</code> 工作流
Pull Requests
示例
集中式工作流
發(fā)布分支
示例
示例
工作方式
維護(hù)分支
Pull Requests
Forking工作流的分支使用方式
解析Pull Request
歷史分支
在 <code>Forking</code> 工作流中使用 <code>Pull Request</code>
沖突解決
功能分支
工作方式
在 <code>Gitflow</code> 工作流中使用 <code>Pull Request</code>
工作方式
在功能分支工作流中使用 <code>Pull Request</code>
示例
工作方式

示例

讓我們一起逐步分解來看看一個常見的小團(tuán)隊(duì)如何用這個工作流來協(xié)作的。有兩個開發(fā)者小明和小紅,看他們是如何開發(fā)自己的功能并提交到中央倉庫上的。

有人先初始化好中央倉庫

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-initialize.png" alt="" />

第一步,有人在服務(wù)器上創(chuàng)建好中央倉庫。如果是新項(xiàng)目,你可以初始化一個空倉庫;否則你要導(dǎo)入已有的 GitSVN 倉庫。

中央倉庫應(yīng)該是個裸倉庫( bare repository ),即沒有工作目錄( working directory )的倉庫??梢杂孟旅娴拿顒?chuàng)建:

ssh user@host
git init --bare /path/to/repo.git

確保寫上有效的 userSSH 的用戶名),host(服務(wù)器的域名或IP地址),/path/to/repo.git(你想存放倉庫的位置)。 注意,為了表示是一個裸倉庫,按照約定加上 .git 擴(kuò)展名到倉庫名上。

所有人克隆中央倉庫

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-clone.png" alt="" />

下一步,各個開發(fā)者創(chuàng)建整個項(xiàng)目的本地拷貝。通過 git clone 命令完成:

git clone ssh://user@host/path/to/repo.git

基于你后續(xù)會持續(xù)和克隆的倉庫做交互的假設(shè),克隆倉庫時 Git 會自動添加遠(yuǎn)程別名 origin 指回『父』倉庫。

小明開發(fā)功能

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-1.png" alt="" />

在小明的本地倉庫中,他使用標(biāo)準(zhǔn)的 Git 過程開發(fā)功能:編輯、暫存(Stage)和提交。 如果你不熟悉暫存區(qū)(Staging Area),這里說明一下:暫存區(qū)用來準(zhǔn)備一個提交,但可以不用把工作目錄中所有的修改內(nèi)容都包含進(jìn)來。 這樣你可以創(chuàng)建一個高度聚焦的提交,盡管你本地修改很多內(nèi)容。

git status # 查看本地倉庫的修改狀態(tài)
git add # 暫存文件
git commit # 提交文件

請記住,因?yàn)檫@些命令生成的是本地提交,小明可以按自己需求反復(fù)操作多次,而不用擔(dān)心中央倉庫上有了什么操作。 對需要多個更簡單更原子分塊的大功能,這個做法是很有用的。

小紅開發(fā)功能

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-2.png" alt="" />

與此同時,小紅在自己的本地倉庫中用相同的編輯、暫存和提交過程開發(fā)功能。和小明一樣,她也不關(guān)心中央倉庫有沒有新提交; 當(dāng)然更不關(guān)心小明在他的本地倉庫中的操作,因?yàn)樗斜镜貍}庫都是私有的。

小明發(fā)布功能

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-3.png" alt="" />

一旦小明完成了他的功能開發(fā),會發(fā)布他的本地提交到中央倉庫中,這樣其它團(tuán)隊(duì)成員可以看到他的修改。他可以用下面的 git push命令

git push origin master

注意,origin 是在小明克隆倉庫時 Git 創(chuàng)建的遠(yuǎn)程中央倉庫別名。master 參數(shù)告訴 Git 推送的分支。 由于中央倉庫自從小明克隆以來還沒有被更新過,所以 push 操作不會有沖突,成功完成。

小紅試著發(fā)布功能

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-4.png" alt="" />

一起來看看在小明發(fā)布修改后,小紅 push 修改會怎么樣?她使用完全一樣的 push 命令:

git push origin master

但她的本地歷史已經(jīng)和中央倉庫有分岐了,Git 拒絕操作并給出下面很長的出錯消息:

error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

這避免了小紅覆寫正式的提交。她要先 pull 小明的更新到她的本地倉庫合并上她的本地修改后,再重試。

小紅在小明的提交之上 rebase

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-5.png" alt="" />

小紅用 git pull 合并上游的修改到自己的倉庫中。 這條命令類似 svn update ——拉取所有上游提交命令到小紅的本地倉庫,并嘗試和她的本地修改合并:

git pull --rebase origin master

--rebase 選項(xiàng)告訴 Git 把小紅的提交移到同步了中央倉庫修改后的 master 分支的頂部,如下圖所示:

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-6.png" alt="" />

如果你忘加了這個選項(xiàng),pull 操作仍然可以完成,但每次 pull 操作要同步中央倉庫中別人修改時,提交歷史會以一個多余的『合并提交』結(jié)尾。 對于集中式工作流,最好是使用 rebase 而不是生成一個合并提交。

小紅解決合并沖突

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-7.png" alt="" />

rebase 操作過程是把本地提交一次一個地遷移到更新了的中央倉庫master 分支之上。

這意味著可能要解決在遷移某個提交時出現(xiàn)的合并沖突,而不是解決包含了所有提交的大型合并時所出現(xiàn)的沖突。 這樣的方式讓你盡可能保持每個提交的聚焦和項(xiàng)目歷史的整潔。反過來,簡化了哪里引入 Bug 的分析,如果有必要,回滾修改也可以做到對項(xiàng)目影響最小。

如果小紅和小明的功能是不相關(guān)的,不大可能在 rebase 過程中有沖突。如果有,Git 在合并有沖突的提交處暫停 rebase 過程,輸出下面的信息并帶上相關(guān)的指令:

CONFLICT (content): Merge conflict in <some-file>

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-8.png" alt="" />

Git 很贊的一點(diǎn)是,任何人可以解決他自己的沖突。在這個例子中,小紅可以簡單的運(yùn)行 git status 命令來查看哪里有問題。

沖突文件列在 Unmerged paths(未合并路徑)一節(jié)中:

# Unmerged paths:
# (use "git reset HEAD <some-file>..." to unstage)
# (use "git add/rm <some-file>..." as appropriate to mark resolution)
#
# both modified: <some-file>

接著小紅編輯這些文件。修改完成后,用老套路暫存這些文件,并讓 git rebase 完成剩下的事:

git add <some-file> 
git rebase --continue

要做的就這些了。Git 會繼續(xù)一個一個地合并后面的提交,如其它的提交有沖突就重復(fù)這個過程。

如果你碰到了沖突,但發(fā)現(xiàn)搞不定,不要驚慌。只要執(zhí)行下面這條命令,就可以回到你執(zhí)行 git pull --rebase 命令前的樣子:

git rebase --abort

小紅成功發(fā)布功能

http://wiki.jikexueyuan.com/project/git-workflow-tutorial/images/git-workflow-svn-9.png" alt="" />

小紅完成和中央倉庫的同步后,就能成功發(fā)布她的修改了:

git push origin master

如你所見,僅使用幾個 Git 命令我們就可以模擬出傳統(tǒng) Subversion 開發(fā)環(huán)境。對于要從 SVN 遷移過來的團(tuán)隊(duì)來說這太好了,但沒有發(fā)揮出 Git 分布式本質(zhì)的優(yōu)勢。

如果你的團(tuán)隊(duì)適應(yīng)了集中式工作流,但想要更流暢的協(xié)作效果,絕對值得探索一下 功能分支工作流 的收益。 通過為一個功能分配一個專門的分支,能夠做到一個新增功能集成到正式項(xiàng)目之前對新功能進(jìn)行深入討論。

上一篇:<code>Gitflow</code> 工作流下一篇:前言