深入理解學(xué)習(xí)Git工作流
個人在學(xué)習(xí)git工作流的過程中,從原有的 SVN 模式很難完全理解git的協(xié)作模式,直到有一天我看到了下面的文章,好多遺留在心中的困惑迎刃而解,于是我將這部分資料進(jìn)行整理放到了github上,歡迎star查看最新更新內(nèi)容, https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md
- 我們以使用SVN的工作流來使用git有什么不妥?
- git 方便的branch在哪里,團隊多人如何協(xié)作?沖突了怎么辦?如何進(jìn)行發(fā)布控制?
- 經(jīng)典的master-發(fā)布、develop-主開發(fā)、hotfix-不過修復(fù)如何避免代碼不經(jīng)過驗證上線?
- 如何在github上面與他人一起協(xié)作,star-fork-pull request是怎樣的流程?
我個人很感激這篇文章,所以進(jìn)行了整理,希望能幫到更多的人。整篇文章由 xirong 整理自 oldratlee 的github,方便統(tǒng)一的學(xué)習(xí)回顧,在此感謝下面兩位的貢獻(xiàn)。
原文鏈接:Git Workflows and Tutorials
簡體中文:由 oldratlee 翻譯在 github 上 git-workflows-and-tutorials
- 一、譯序
- 二、Git工作流指南
- 2.1 集中式工作流
- 2.1.1 工作方式
- 2.1.2 沖突解決
- 2.1.3 示例
- 有人先初始化好中央倉庫
- 所有人克隆中央倉庫
- 小明開發(fā)功能
- 小紅開發(fā)功能
- 小明發(fā)布功能
- 小紅試著發(fā)布功能
- 小紅在小明的提交之上rebase
- 小紅解決合并沖突
- 小紅成功發(fā)布功能
- 2.2 功能分支工作流
- 2.2.1 工作方式
- 2.2.2 Pull Requests
- 2.2.3 示例
- 小紅開始開發(fā)一個新功能
- 小紅要去吃個午飯
- 小紅完成功能開發(fā)
- 小黑收到Pull Request
- 小紅再做修改
- 小紅發(fā)布她的功能
- 與此同時,小明在做和小紅一樣的事
- 2.3 Gitflow工作流
- 2.3.1 工作方式
- 2.3.2 歷史分支
- 2.3.3 功能分支
- 2.3.4 發(fā)布分支
- 2.3.5 維護(hù)分支
- 2.3.6 示例
- 創(chuàng)建開發(fā)分支
- 小紅和小明開始開發(fā)新功能
- 小紅完成功能開發(fā)
- 小紅開始準(zhǔn)備發(fā)布
- 小紅完成發(fā)布
- 最終用戶發(fā)現(xiàn)Bug
- 2.4 Forking工作流
- 2.4.1 工作方式
- 2.4.2 正式倉庫
- 2.4.3 Forking工作流的分支使用方式
- 2.4.4 示例
- 項目維護(hù)者初始化正式倉庫
- 開發(fā)者fork正式倉庫
- 開發(fā)者克隆自己fork出來的倉庫
- 開發(fā)者開發(fā)自己的功能
- 開發(fā)者發(fā)布自己的功能
- 項目維護(hù)者集成開發(fā)者的功能
- 開發(fā)者和正式倉庫做同步
- 2.5 Pull Requests
- 2.5.1 解析Pull Request
- 2.5.2 工作方式
- 2.5.3 在功能分支工作流中使用Pull Request
- 2.5.4 在Gitflow工作流中使用Pull Request
- 2.5.5 在Forking工作流中使用Pull Request
- 2.5.6 示例
- 小紅fork正式項目
- 小紅克隆她的Bitbucket倉庫
- 小紅開發(fā)新功能
- 小紅push功能到她的Bitbucket倉庫中
- 小紅發(fā)起Pull Request
- 小明review Pull Request
- 小紅補加提交
- 小明接受Pull Request
- 2.1 集中式工作流
一、譯序
工作流其實不是一個初級主題,背后的本質(zhì)問題其實是有效的項目流程管理和高效的開發(fā)協(xié)同約定,不僅是Git
或SVN
等VCS
或SCM
工具的使用。
這篇指南以大家在SVN
中已經(jīng)廣為熟悉使用的集中式工作流作為起點,循序漸進(jìn)地演進(jìn)到其它高效的分布式工作流,還介紹了如何配合使用便利的Pull Request
功能,體系地講解了各種工作流的應(yīng)用。
行文中實踐原則和操作示例并重,對于Git
的資深玩家可以梳理思考提升,而新接觸的同學(xué),也可以跟著step-by-step操作來操練學(xué)習(xí)并在實際工作中上手使用。
關(guān)于Git
工作流主題,網(wǎng)上體系的中文資料不多,主要是零散的操作說明,希望這篇文章能讓你更深入理解并在工作中靈活有效地使用起來。
PS:
文中Pull Request
的介紹用的是Bitbucket
代碼托管服務(wù),由于和GitHub
基本一樣,如果你用的是GitHub
(我自己也主要使用GitHub
托管代碼),不影響理解和操作。
PPS:
本指南循序漸進(jìn)地講解工作流,如果Git
用的不多,可以從前面的講的工作流開始操練。操作過程去感受指南的講解:解決什么問題、如何解決問題,這樣理解就深了,也方便活用。
Gitflow
工作流是經(jīng)典模型,體現(xiàn)了工作流的經(jīng)驗和精髓。隨著項目過程復(fù)雜化,會感受到這個工作流中深思熟慮和威力!
Forking
工作流是協(xié)作的(GitHub
風(fēng)格)可以先看看Github
的Help:Fork A Repo和Using pull requests 。照著操作,給一個Github
項目貢獻(xiàn)你的提交,有操作經(jīng)驗再看指南容易意會。指南中給了自己實現(xiàn)Fork
的方法:Fork
就是服務(wù)端的克隆。在指南的操練中使用代碼托管服務(wù)(如GitHub
、Bitbucket
),可以點一下按鈕就讓開發(fā)者完成倉庫的fork
操作。
:see_no_evil: 自己理解粗淺,翻譯中不足和不對之處,歡迎建議(提交Issue)和指正(Fork后提交代碼)!
#p#
二、Git
工作流指南
:point_right: 工作流有各式各樣的用法,但也正因此使得在實際工作中如何上手使用變得很頭大。這篇指南通過總覽公司團隊中最常用的幾種Git
工作流讓大家可以上手使用。
在閱讀的過程中請記住,本文中的幾種工作流是作為方案指導(dǎo)而不是條例規(guī)定。在展示了各種工作流可能的用法后,你可以從不同的工作流中挑選或揉合出一個滿足你自己需求的工作流。
2.1 集中式工作流
如果你的開發(fā)團隊成員已經(jīng)很熟悉Subversion
,集中式工作流讓你無需去適應(yīng)一個全新流程就可以體驗Git
帶來的收益。這個工作流也可以作為向更Git
風(fēng)格工作流遷移的友好過渡。
轉(zhuǎn)到分布式版本控制系統(tǒng)看起來像個令人生畏的任務(wù),但不改變已用的工作流你也可以用上Git
帶來的收益。團隊可以用和Subversion
完全不變的方式來開發(fā)項目。
但使用Git
加強開發(fā)的工作流,Git
有相比SVN
的幾個優(yōu)勢。
首先,每個開發(fā)可以有屬于自己的整個工程的本地拷貝。隔離的環(huán)境讓各個開發(fā)者的工作和項目的其他部分修改獨立開來 ——
即自由地提交到自己的本地倉庫,先完全忽略上游的開發(fā),直到方便的時候再把修改反饋上去。
其次,Git
提供了強壯的分支和合并模型。不像SVN
,Git
的分支設(shè)計成可以做為一種用來在倉庫之間集成代碼和分享修改的『失敗安全』的機制。
2.1.1 工作方式
像Subversion
一樣,集中式工作流以中央倉庫作為項目所有修改的單點實體。相比SVN
缺省的開發(fā)分支trunk
,Git
叫做master
,所有修改提交到這個分支上。本工作流只用到master
這一個分支。
開發(fā)者開始先克隆中央倉庫。在自己的項目拷貝中像SVN
一樣的編輯文件和提交修改;但修改是存在本地的,和中央倉庫是完全隔離的。開發(fā)者可以把和上游的同步延后到一個方便時間點。
要發(fā)布修改到正式項目中,開發(fā)者要把本地master
分支的修改『推』到中央倉庫中。這相當(dāng)于svn commit
操作,但push
操作會把所有還不在中央倉庫的本地提交都推上去。
2.1.2 沖突解決
中央倉庫代表了正式項目,所以提交歷史應(yīng)該被尊重且是穩(wěn)定不變的。如果開發(fā)者本地的提交歷史和中央倉庫有分歧,Git
會拒絕push
提交否則會覆蓋已經(jīng)在中央庫的正式提交。
在開發(fā)者提交自己功能修改到中央庫前,需要先fetch
在中央庫的新增提交,rebase
自己提交到中央庫提交歷史之上。
這樣做的意思是在說,『我要把自己的修改加到別人已經(jīng)完成的修改上。』最終的結(jié)果是一個完美的線性歷史,就像以前的SVN
的工作流中一樣。
如果本地修改和上游提交有沖突,Git
會暫停rebase
過程,給你手動解決沖突的機會。Git
解決合并沖突,用和生成提交一樣的git status
和git add
命令,很一致方便。還有一點,如果解決沖突時遇到麻煩,Git
可以很簡單中止整個rebase
操作,重來一次(或者讓別人來幫助解決)。
2.1.3 示例
讓我們一起逐步分解來看看一個常見的小團隊如何用這個工作流來協(xié)作的。有兩個開發(fā)者小明和小紅,看他們是如何開發(fā)自己的功能并提交到中央倉庫上的。
有人先初始化好中央倉庫
第一步,有人在服務(wù)器上創(chuàng)建好中央倉庫。如果是新項目,你可以初始化一個空倉庫;否則你要導(dǎo)入已有的Git
或SVN
倉庫。
中央倉庫應(yīng)該是個裸倉庫(bare repository
),即沒有工作目錄(working directory
)的倉庫??梢杂孟旅娴拿顒?chuàng)建:
ssh user@host
git init --bare /path/to/repo.git
確保寫上有效的user
(SSH
的用戶名),host
(服務(wù)器的域名或IP地址),/path/to/repo.git
(你想存放倉庫的位置)。
注意,為了表示是一個裸倉庫,按照約定加上.git
擴展名到倉庫名上。
所有人克隆中央倉庫
下一步,各個開發(fā)者創(chuàng)建整個項目的本地拷貝。通過git clone
命令完成:
git clone ssh://user@host/path/to/repo.git
基于你后續(xù)會持續(xù)和克隆的倉庫做交互的假設(shè),克隆倉庫時Git
會自動添加遠(yuǎn)程別名origin
指回『父』倉庫。
小明開發(fā)功能
在小明的本地倉庫中,他使用標(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 # 提交文件
請記住,因為這些命令生成的是本地提交,小明可以按自己需求反復(fù)操作多次,而不用擔(dān)心中央倉庫上有了什么操作。
對需要多個更簡單更原子分塊的大功能,這個做法是很有用的。
小紅開發(fā)功能
與此同時,小紅在自己的本地倉庫中用相同的編輯、暫存和提交過程開發(fā)功能。和小明一樣,她也不關(guān)心中央倉庫有沒有新提交;
當(dāng)然更不關(guān)心小明在他的本地倉庫中的操作,因為所有本地倉庫都是私有的。
小明發(fā)布功能
一旦小明完成了他的功能開發(fā),會發(fā)布他的本地提交到中央倉庫中,這樣其它團隊成員可以看到他的修改。他可以用下面的git push
命令:
git push origin master
注意,origin
是在小明克隆倉庫時Git
創(chuàng)建的遠(yuǎn)程中央倉庫別名。master
參數(shù)告訴Git
推送的分支。
由于中央倉庫自從小明克隆以來還沒有被更新過,所以push
操作不會有沖突,成功完成。
小紅試著發(fā)布功能
一起來看看在小明發(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
小紅用git pull
合并上游的修改到自己的倉庫中。
這條命令類似svn update
——拉取所有上游提交命令到小紅的本地倉庫,并嘗試和她的本地修改合并:
git pull --rebase origin master
--rebase
選項告訴Git
把小紅的提交移到同步了中央倉庫修改后的master
分支的頂部,如下圖所示:
如果你忘加了這個選項,pull
操作仍然可以完成,但每次pull
操作要同步中央倉庫中別人修改時,提交歷史會以一個多余的『合并提交』結(jié)尾。
對于集中式工作流,最好是使用rebase
而不是生成一個合并提交。
小紅解決合并沖突
rebase
操作過程是把本地提交一次一個地遷移到更新了的中央倉庫master
分支之上。
這意味著可能要解決在遷移某個提交時出現(xiàn)的合并沖突,而不是解決包含了所有提交的大型合并時所出現(xiàn)的沖突。
這樣的方式讓你盡可能保持每個提交的聚焦和項目歷史的整潔。反過來,簡化了哪里引入Bug
的分析,如果有必要,回滾修改也可以做到對項目影響最小。
如果小紅和小明的功能是相關(guān)的,不大可能在rebase
過程中有沖突。如果有,Git
在合并有沖突的提交處暫停rebase
過程,輸出下面的信息并帶上相關(guān)的指令:
CONFLICT (content): Merge conflict in <some-file>
Git
很贊的一點是,任何人可以解決他自己的沖突。在這個例子中,小紅可以簡單的運行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ā)布功能
小紅完成和中央倉庫的同步后,就能成功發(fā)布她的修改了:
git push origin master
如你所見,僅使用幾個Git
命令我們就可以模擬出傳統(tǒng)Subversion
開發(fā)環(huán)境。對于要從SVN
遷移過來的團隊來說這太好了,但沒有發(fā)揮出Git
分布式本質(zhì)的優(yōu)勢。
如果你的團隊適應(yīng)了集中式工作流,但想要更流暢的協(xié)作效果,絕對值得探索一下 功能分支工作流
的收益。
通過為一個功能分配一個專門的分支,能夠做到一個新增功能集成到正式項目之前對新功能進(jìn)行深入討論。
2.2 功能分支工作流
功能分支工作流以集中式工作流為基礎(chǔ),不同的是為各個新功能分配一個專門的分支來開發(fā)。這樣可以在把新功能集成到正式項目前,用Pull Requests
的方式討論變更。
一旦你玩轉(zhuǎn)了集中式工作流,在開發(fā)過程中可以很簡單地加上功能分支,用來鼓勵開發(fā)者之間協(xié)作和簡化交流。
功能分支工作流背后的核心思路是所有的功能開發(fā)應(yīng)該在一個專門的分支,而不是在master
分支上。
這個隔離可以方便多個開發(fā)者在各自的功能上開發(fā)而不會弄亂主干代碼。
另外,也保證了master
分支的代碼一定不會是有問題的,極大有利于集成環(huán)境。
功能開發(fā)隔離也讓pull requests
工作流成功可能,
pull requests
工作流能為每個分支發(fā)起一個討論,在分支合入正式項目之前,給其它開發(fā)者有表示贊同的機會。
另外,如果你在功能開發(fā)中有問題卡住了,可以開一個pull requests
來向同學(xué)們征求建議。
這些做法的重點就是,pull requests
讓團隊成員之間互相評論工作變成非常方便!
2.2.1 工作方式
功能分支工作流仍然用中央倉庫,并且master
分支還是代表了正式項目的歷史。
但不是直接提交本地歷史到各自的本地master
分支,開發(fā)者每次在開始新功能前先創(chuàng)建一個新分支。
功能分支應(yīng)該有個有描述性的名字,比如animated-menu-items
或issue-#1061
,這樣可以讓分支有個清楚且高聚焦的用途。
在master
分支和功能分支之間,Git
是沒有技術(shù)上的區(qū)別,所以開發(fā)者可以用和集中式工作流中完全一樣的方式編輯、暫存和提交修改到功能分支上。
另外,功能分支也可以(且應(yīng)該)push
到中央倉庫中。這樣不修改正式代碼就可以和其它開發(fā)者分享提交的功能。
由于master
僅有的一個『特殊』分支,在中央倉庫上存多個功能分支不會有任何問題。當(dāng)然,這樣做也可以很方便地備份各自的本地提交。
2.2.2 Pull Requests
功能分支除了可以隔離功能的開發(fā),也使得通過Pull Requests
討論變更成為可能。
一旦某個開發(fā)完成一個功能,不是立即合并到master
,而是push
到中央倉庫的功能分支上并發(fā)起一個Pull Request
請求去合并修改到master
。
在修改成為主干代碼前,這讓其它的開發(fā)者有機會先去Review
變更。
Code Review
是Pull Requests
的一個重要的收益,但Pull Requests
目的是討論代碼一個通用方式。
你可以把Pull Requests
作為專門給某個分支的討論。這意味著可以在更早的開發(fā)過程中就可以進(jìn)行Code Review
。
比如,一個開發(fā)者開發(fā)功能需要幫助時,要做的就是發(fā)起一個Pull Request
,相關(guān)的人就會自動收到通知,在相關(guān)的提交旁邊能看到需要幫助解決的問題。
一旦Pull Request
被接受了,發(fā)布功能要做的就和集中式工作流就很像了。
首先,確定本地的master
分支和上游的master
分支是同步的。然后合并功能分支到本地master
分支并push
已經(jīng)更新的本地master
分支到中央倉庫。
倉庫管理的產(chǎn)品解決方案像Bitbucket
或Stash
,可以良好地支持Pull Requests
。可以看看Stash
的Pull Requests
文檔。
2.2.3 示例
下面的示例演示了如何把Pull Requests
作為Code Review
的方式,但注意Pull Requests
可以用于很多其它的目的。
小紅開始開發(fā)一個新功能
在開始開發(fā)功能前,小紅需要一個獨立的分支。使用下面的命令新建一個分支:
git checkout -b marys-feature master
這個命令檢出一個基于master
名為marys-feature
的分支,Git
的-b
選項表示如果分支還不存在則新建分支。
這個新分支上,小紅按老套路編輯、暫存和提交修改,按需要提交以實現(xiàn)功能:
git status
git add <some-file>
git commit
小紅要去吃個午飯
早上小紅為新功能添加一些提交。
去吃午飯前,push
功能分支到中央倉庫是很好的做法,這樣可以方便地備份,如果和其它開發(fā)協(xié)作,也讓他們可以看到小紅的提交。
git push -u origin marys-feature
這條命令push
marys-feature
分支到中央倉庫(origin
),-u
選項設(shè)置本地分支去跟蹤遠(yuǎn)程對應(yīng)的分支。
設(shè)置好跟蹤的分支后,小紅就可以使用git push
命令省去指定推送分支的參數(shù)。
小紅完成功能開發(fā)
小紅吃完午飯回來,完成整個功能的開發(fā)。在合并到master
之前,
她發(fā)起一個Pull Request
讓團隊的其它人知道功能已經(jīng)完成。但首先,她要確認(rèn)中央倉庫中已經(jīng)有她最近的提交:
git push
然后,在她的Git
GUI
客戶端中發(fā)起Pull Request
,請求合并marys-feature
到master
,團隊成員會自動收到通知。
Pull Request
很酷的是可以在相關(guān)的提交旁邊顯示評注,所以你可以很對某個變更集提問。
小黑收到Pull Request
小黑收到了Pull Request
后會查看marys-feature
的修改。決定在合并到正式項目前是否要做些修改,且通過Pull Request
和小紅來回地討論。
小紅再做修改
要再做修改,小紅用和功能第一個迭代完全一樣的過程。編輯、暫存、提交并push
更新到中央倉庫。小紅這些活動都會顯示在Pull Request
上,小黑可以斷續(xù)做評注。
如果小黑有需要,也可以把marys-feature
分支拉到本地,自己來修改,他加的提交也會一樣顯示在Pull Request
上。
小紅發(fā)布她的功能
一旦小黑可以的接受Pull Request
,就可以合并功能到穩(wěn)定項目代碼中(可以由小黑或是小紅來做這個操作):
git checkout master
git pull
git pull origin marys-feature
git push
無論誰來做合并,首先要檢出master
分支并確認(rèn)是它是最新的。然后執(zhí)行git pull origin marys-feature
合并marys-feature
分支到和已經(jīng)和遠(yuǎn)程一致的本地master
分支。
你可以使用簡單git merge marys-feature
命令,但前面的命令可以保證總是最新的新功能分支。
最后更新的master
分支要重新push
回到origin
。
這個過程常常會生成一個合并提交。有些開發(fā)者喜歡有合并提交,因為它像一個新功能和原來代碼基線的連通符。
但如果你偏愛線性的提交歷史,可以在執(zhí)行合并時rebase
新功能到master
分支的頂部,這樣生成一個快進(jìn)(fast-forward
)的合并。
一些GUI
客戶端可以只要點一下『接受』按鈕執(zhí)行好上面的命令來自動化Pull Request
接受過程。
如果你的不能這樣,至少在功能合并到master
分支后能自動關(guān)閉Pull Request
。
與此同時,小明在做和小紅一樣的事
當(dāng)小紅和小黑在marys-feature
上工作并討論她的Pull Request
的時候,小明在自己的功能分支上做完全一樣的事。
通過隔離功能到獨立的分支上,每個人都可以自主的工作,當(dāng)然必要的時候在開發(fā)者之間分享變更還是比較繁瑣的。
到了這里,但愿你發(fā)現(xiàn)了功能分支可以很直接地在 集中式工作流
的僅有的master
分支上完成多功能的開發(fā)。
另外,功能分支還使用了Pull Request
,使得可以在你的版本控制GUI
客戶端中討論某個提交。
功能分支工作流是開發(fā)項目異常靈活的方式。問題是,有時候太靈活了。對于大型團隊,常常需要給不同分支分配一個更具體的角色。
Gitflow
工作流是管理功能開發(fā)、發(fā)布準(zhǔn)備和維護(hù)的常用模式。
#p#
2.3 Gitflow
工作流
Gitflow
工作流通過為功能開發(fā)、發(fā)布準(zhǔn)備和維護(hù)分配獨立的分支,讓發(fā)布迭代過程更流暢。嚴(yán)格的分支模型也為大型項目提供了一些非常必要的結(jié)構(gòu)。
這節(jié)介紹的Gitflow
工作流借鑒自在nvie的Vincent Driessen。
Gitflow
工作流定義了一個圍繞項目發(fā)布的嚴(yán)格分支模型。雖然比功能分支工作流復(fù)雜幾分,但提供了用于一個健壯的用于管理大型項目的框架。
Gitflow
工作流沒有用超出功能分支工作流的概念和命令,而是為不同的分支分配一個很明確的角色,并定義分支之間如何和什么時候進(jìn)行交互。
除了使用功能分支,在做準(zhǔn)備、維護(hù)和記錄發(fā)布也使用各自的分支。
當(dāng)然你可以用上功能分支工作流所有的好處:Pull Requests
、隔離實驗性開發(fā)和更高效的協(xié)作。
2.3.1 工作方式
Gitflow
工作流仍然用中央倉庫作為所有開發(fā)者的交互中心。和其它的工作流一樣,開發(fā)者在本地工作并push
分支到要中央倉庫中。
2.3.2 歷史分支
相對使用僅有的一個master
分支,Gitflow
工作流使用2個分支來記錄項目的歷史。master
分支存儲了正式發(fā)布的歷史,而develop
分支作為功能的集成分支。
這樣也方便master
分支上的所有提交分配一個版本號。
剩下要說明的問題圍繞著這2個分支的區(qū)別展開。
2.3.3 功能分支
每個新功能位于一個自己的分支,這樣可以push
到中央倉庫以備份和協(xié)作。
但功能分支不是從master
分支上拉出新分支,而是使用develop
分支作為父分支。當(dāng)新功能完成時,合并回develop
分支。
新功能提交應(yīng)該從不直接與master
分支交互。
注意,從各種含義和目的上來看,功能分支加上develop
分支就是功能分支工作流的用法。但Gitflow
工作流沒有在這里止步。
2.3.4 發(fā)布分支
一旦develop
分支上有了做一次發(fā)布(或者說快到了既定的發(fā)布日)的足夠功能,就從develop
分支上fork
一個發(fā)布分支。
新建的分支用于開始發(fā)布循環(huán),所以從這個時間點開始之后新的功能不能再加到這個分支上——
這個分支只應(yīng)該做Bug
修復(fù)、文檔生成和其它面向發(fā)布任務(wù)。
一旦對外發(fā)布的工作都完成了,發(fā)布分支合并到master
分支并分配一個版本號打好Tag
。
另外,這些從新建發(fā)布分支以來的做的修改要合并回develop
分支。
使用一個用于發(fā)布準(zhǔn)備的專門分支,使得一個團隊可以在完善當(dāng)前的發(fā)布版本的同時,另一個團隊可以繼續(xù)開發(fā)下個版本的功能。
這也打造定義良好的開發(fā)階段(比如,可以很輕松地說,『這周我們要做準(zhǔn)備發(fā)布版本4.0』,并且在倉庫的目錄結(jié)構(gòu)中可以實際看到)。
常用的分支約定:
用于新建發(fā)布分支的分支: develop
用于合并的分支: master
分支命名: release-* 或 release/*
2.3.5 維護(hù)分支
維護(hù)分支或說是熱修復(fù)(hotfix
)分支用于生成快速給產(chǎn)品發(fā)布版本(production releases
)打補丁,這是唯一可以直接從master
分支fork
出來的分支。
修復(fù)完成,修改應(yīng)該馬上合并回master
分支和develop
分支(當(dāng)前的發(fā)布分支),master
分支應(yīng)該用新的版本號打好Tag
。
為Bug
修復(fù)使用專門分支,讓團隊可以處理掉問題而不用打斷其它工作或是等待下一個發(fā)布循環(huán)。
你可以把維護(hù)分支想成是一個直接在master
分支上處理的臨時發(fā)布。
2.3.6 示例
下面的示例演示本工作流如何用于管理單個發(fā)布循環(huán)。假設(shè)你已經(jīng)創(chuàng)建了一個中央倉庫。
創(chuàng)建開發(fā)分支
第一步為master
分支配套一個develop
分支。簡單來做可以本地創(chuàng)建一個空的develop
分支,push
到服務(wù)器上:
git branch develop
git push -u origin develop
以后這個分支將會包含了項目的全部歷史,而master
分支將只包含了部分歷史。其它開發(fā)者這時應(yīng)該克隆中央倉庫,建好develop
分支的跟蹤分支:
git clone ssh://user@host/path/to/repo.git
git checkout -b develop origin/develop
現(xiàn)在每個開發(fā)都有了這些歷史分支的本地拷貝。
小紅和小明開始開發(fā)新功能
這個示例中,小紅和小明開始各自的功能開發(fā)。他們需要為各自的功能創(chuàng)建相應(yīng)的分支。新分支不是基于master
分支,而是應(yīng)該基于develop
分支:
git checkout -b some-feature develop
他們用老套路添加提交到各自功能分支上:編輯、暫存、提交:
git status
git add <some-file>
git commit
小紅完成功能開發(fā)
添加了提交后,小紅覺得她的功能OK了。如果團隊使用Pull Requests
,這時候可以發(fā)起一個用于合并到develop
分支。
否則她可以直接合并到她本地的develop
分支后push
到中央倉庫:
git pull origin develop
git checkout develop
git merge some-feature
git push
git branch -d some-feature
第一條命令在合并功能前確保develop
分支是最新的。注意,功能決不應(yīng)該直接合并到master
分支。
沖突解決方法和集中式工作流一樣。
小紅開始準(zhǔn)備發(fā)布
這個時候小明正在實現(xiàn)他的功能,小紅開始準(zhǔn)備她的第一個項目正式發(fā)布。
像功能開發(fā)一樣,她用一個新的分支來做發(fā)布準(zhǔn)備。這一步也確定了發(fā)布的版本號:
git checkout -b release-0.1 develop
這個分支是清理發(fā)布、執(zhí)行所有測試、更新文檔和其它為下個發(fā)布做準(zhǔn)備操作的地方,像是一個專門用于改善發(fā)布的功能分支。
只要小紅創(chuàng)建這個分支并push
到中央倉庫,這個發(fā)布就是功能凍結(jié)的。任何不在develop
分支中的新功能都推到下個發(fā)布循環(huán)中。
小紅完成發(fā)布
一旦準(zhǔn)備好了對外發(fā)布,小紅合并修改到master
分支和develop
分支上,刪除發(fā)布分支。合并回develop
分支很重要,因為在發(fā)布分支中已經(jīng)提交的更新需要在后面的新功能中也要是可用的。
另外,如果小紅的團隊要求Code Review
,這是一個發(fā)起Pull Request
的理想時機。
git checkout master
git merge release-0.1
git push
git checkout develop
git merge release-0.1
git push
git branch -d release-0.1
發(fā)布分支是作為功能開發(fā)(develop
分支)和對外發(fā)布(master
分支)間的緩沖。只要有合并到master
分支,就應(yīng)該打好Tag
以方便跟蹤。
git tag -a 0.1 -m "Initial public release" master
git push --tags
Git
有提供各種勾子(hook
),即倉庫有事件發(fā)生時觸發(fā)執(zhí)行的腳本。
可以配置一個勾子,在你push
中央倉庫的master
分支時,自動構(gòu)建好對外發(fā)布。
最終用戶發(fā)現(xiàn)Bug
對外發(fā)布后,小紅回去和小明一起做下個發(fā)布的新功能開發(fā),直到有最終用戶開了一個Ticket
抱怨當(dāng)前版本的一個Bug
。
為了處理Bug
,小紅(或小明)從master
分支上拉出了一個維護(hù)分支,提交修改以解決問題,然后直接合并回master
分支:
git checkout -b issue-#001 master
# Fix the bug
git checkout master
git merge issue-#001
git push
就像發(fā)布分支,維護(hù)分支中新加這些重要修改需要包含到develop
分支中,所以小紅要執(zhí)行一個合并操作。然后就可以安全地刪除這個分支了:
git checkout develop
git merge issue-#001
git push
git branch -d issue-#001
到了這里,但愿你對集中式工作流、功能分支工作流和Gitflow
工作流已經(jīng)感覺很舒適了。
你應(yīng)該也牢固的掌握了本地倉庫的潛能,push
/pull
模式和Git
健壯的分支和合并模型。
記住,這里演示的工作流只是可能用法的例子,而不是在實際工作中使用Git
不可違逆的條例。
所以不要畏懼按自己需要對工作流的用法做取舍。不變的目標(biāo)就是讓Git
為你所用。
#p#
2.4 Forking工作流
Forking
工作流是分布式工作流,充分利用了Git
在分支和克隆上的優(yōu)勢??梢园踩煽康毓芾泶髨F隊的開發(fā)者(developer
),并能接受不信任貢獻(xiàn)者(contributor
)的提交。
Forking
工作流和前面討論的幾種工作流有根本的不同,這種工作流不是使用單個服務(wù)端倉庫作為『中央』代碼基線,而讓各個開發(fā)者都有一個服務(wù)端倉庫。這意味著各個代碼貢獻(xiàn)者有2個Git
倉庫而不是1個:一個本地私有的,另一個服務(wù)端公開的。
Forking
工作流的一個主要優(yōu)勢是,貢獻(xiàn)的代碼可以被集成,而不需要所有人都能push
代碼到僅有的中央倉庫中。
開發(fā)者push
到自己的服務(wù)端倉庫,而只有項目維護(hù)者才能push
到正式倉庫。
這樣項目維護(hù)者可以接受任何開發(fā)者的提交,但無需給他正式代碼庫的寫權(quán)限。
效果就是一個分布式的工作流,能為大型、自發(fā)性的團隊(包括了不受信的第三方)提供靈活的方式來安全的協(xié)作。
也讓這個工作流成為開源項目的理想工作流。
2.4.1 工作方式
和其它的Git
工作流一樣,Forking
工作流要先有一個公開的正式倉庫存儲在服務(wù)器上。
但一個新的開發(fā)者想要在項目上工作時,不是直接從正式倉庫克隆,而是fork
正式項目在服務(wù)器上創(chuàng)建一個拷貝。
這個倉庫拷貝作為他個人公開倉庫 ——
其它開發(fā)者不允許push
到這個倉庫,但可以pull
到修改(后面我們很快就會看這點很重要)。
在創(chuàng)建了自己服務(wù)端拷貝之后,和之前的工作流一樣,開發(fā)者執(zhí)行git clone
命令克隆倉庫到本地機器上,作為私有的開發(fā)環(huán)境。
要提交本地修改時,push
提交到自己公開倉庫中 —— 而不是正式倉庫中。
然后,給正式倉庫發(fā)起一個pull request
,讓項目維護(hù)者知道有更新已經(jīng)準(zhǔn)備好可以集成了。
對于貢獻(xiàn)的代碼,pull request
也可以很方便地作為一個討論的地方。
為了集成功能到正式代碼庫,維護(hù)者pull
貢獻(xiàn)者的變更到自己的本地倉庫中,檢查變更以確保不會讓項目出錯,
合并變更到自己本地的master
分支,
然后push
master
分支到服務(wù)器的正式倉庫中。
到此,貢獻(xiàn)的提交成為了項目的一部分,其它的開發(fā)者應(yīng)該執(zhí)行pull
操作與正式倉庫同步自己本地倉庫。
2.4.2 正式倉庫
在Forking
工作流中,『官方』倉庫的叫法只是一個約定,理解這點很重要。
從技術(shù)上來看,各個開發(fā)者倉庫和正式倉庫在Git
看來沒有任何區(qū)別。
事實上,讓正式倉庫之所以正式的唯一原因是它是項目維護(hù)者的公開倉庫。
2.4.3 Forking
工作流的分支使用方式
所有的個人公開倉庫實際上只是為了方便和其它的開發(fā)者共享分支。
各個開發(fā)者應(yīng)該用分支隔離各個功能,就像在功能分支工作流和Gitflow
工作流一樣。
唯一的區(qū)別是這些分支被共享了。在Forking
工作流中這些分支會被pull
到另一個開發(fā)者的本地倉庫中,而在功能分支工作流和Gitflow
工作流中是直接被push
到正式倉庫中。
2.4.4 示例
項目維護(hù)者初始化正式倉庫
和任何使用Git
項目一樣,第一步是創(chuàng)建在服務(wù)器上一個正式倉庫,讓所有團隊成員都可以訪問到。
通常這個倉庫也會作為項目維護(hù)者的公開倉庫。
公開倉庫應(yīng)該是裸倉庫,不管是不是正式代碼庫。
所以項目維護(hù)者會運行像下面的命令來搭建正式倉庫:
ssh user@host
git init --bare /path/to/repo.git
Bitbucket
和Stash
提供了一個方便的GUI
客戶端以完成上面命令行做的事。
這個搭建中央倉庫的過程和前面提到的工作流完全一樣。
如果有現(xiàn)存的代碼庫,維護(hù)者也要push
到這個倉庫中。
開發(fā)者fork
正式倉庫
其它所有的開發(fā)需要fork
正式倉庫。
可以用git clone
命令用SSH
協(xié)議連通到服務(wù)器,
拷貝倉庫到服務(wù)器另一個位置 —— 是的,fork
操作基本上就只是一個服務(wù)端的克隆。
Bitbucket
和Stash
上可以點一下按鈕就讓開發(fā)者完成倉庫的fork
操作。
這一步完成后,每個開發(fā)都在服務(wù)端有一個自己的倉庫。和正式倉庫一樣,這些倉庫應(yīng)該是裸倉庫。
開發(fā)者克隆自己fork
出來的倉庫
下一步,各個開發(fā)者要克隆自己的公開倉庫,用熟悉的git clone
命令。
在這個示例中,假定用Bitbucket
托管了倉庫。記住,如果這樣的話各個開發(fā)者需要有各自的Bitbucket
賬號,
使用下面命令克隆服務(wù)端自己的倉庫:
git clone https://user@bitbucket.org/user/repo.git
相比前面介紹的工作流只用了一個origin
遠(yuǎn)程別名指向中央倉庫,Forking
工作流需要2個遠(yuǎn)程別名 ——
一個指向正式倉庫,另一個指向開發(fā)者自己的服務(wù)端倉庫。別名的名字可以任意命名,常見的約定是使用origin
作為遠(yuǎn)程克隆的倉庫的別名
(這個別名會在運行git clone
自動創(chuàng)建),upstream
(上游)作為正式倉庫的別名。
git remote add upstream https://bitbucket.org/maintainer/repo
需要自己用上面的命令創(chuàng)建upstream
別名。這樣可以簡單地保持本地倉庫和正式倉庫的同步更新。
注意,如果上游倉庫需要認(rèn)證(比如不是開源的),你需要提供用戶:
git remote add upstream https://user@bitbucket.org/maintainer/repo.git
這時在克隆和pull
正式倉庫時,需要提供用戶的密碼。
開發(fā)者開發(fā)自己的功能
在剛克隆的本地倉庫中,開發(fā)者可以像其它工作流一樣的編輯代碼、提交修改和新建分支:
git checkout -b some-feature
# Edit some code
git commit -a -m "Add first draft of some feature"
所有的修改都是私有的直到push
到自己公開倉庫中。如果正式項目已經(jīng)往前走了,可以用git pull
命令獲得新的提交:
git pull upstream master
由于開發(fā)者應(yīng)該都在專門的功能分支上工作,pull
操作結(jié)果會都是快進(jìn)合并。
開發(fā)者發(fā)布自己的功能
一旦開發(fā)者準(zhǔn)備好了分享新功能,需要做二件事。
首先,通過push
他的貢獻(xiàn)代碼到自己的公開倉庫中,讓其它的開發(fā)者都可以訪問到。
他的origin
遠(yuǎn)程別名應(yīng)該已經(jīng)有了,所以要做的就是:
git push origin feature-branch
這里和之前的工作流的差異是,origin
遠(yuǎn)程別名指向開發(fā)者自己的服務(wù)端倉庫,而不是正式倉庫。
第二件事,開發(fā)者要通知項目維護(hù)者,想要合并他的新功能到正式庫中。
Bitbucket
和Stash
提供了Pull Request
按鈕,彈出表單讓你指定哪個分支要合并到正式倉庫。
一般你會想集成你的功能分支到上游遠(yuǎn)程倉庫的master
分支中。
項目維護(hù)者集成開發(fā)者的功能
當(dāng)項目維護(hù)者收到pull request
,他要做的是決定是否集成它到正式代碼庫中。有二種方式來做:
-
直接在
pull request
中查看代碼 -
pull
代碼到他自己的本地倉庫,再手動合并
第一種做法更簡單,維護(hù)者可以在GUI
中查看變更的差異,做評注和執(zhí)行合并。
但如果出現(xiàn)了合并沖突,需要第二種做法來解決。這種情況下,維護(hù)者需要從開發(fā)者的服務(wù)端倉庫中fetch
功能分支,
合并到他本地的master
分支,解決沖突:
git fetch https://bitbucket.org/user/repo feature-branch
# 查看變更
git checkout master
git merge FETCH_HEAD
變更集成到本地的master
分支后,維護(hù)者要push
變更到服務(wù)器上的正式倉庫,這樣其它的開發(fā)者都能訪問到:
git push origin master
注意,維護(hù)者的origin
是指向他自己公開倉庫的,即是項目的正式代碼庫。到此,開發(fā)者的貢獻(xiàn)完全集成到了項目中。
開發(fā)者和正式倉庫做同步
由于正式代碼庫往前走了,其它的開發(fā)需要和正式倉庫做同步:
git pull upstream master
如果你之前是使用SVN
,Forking
工作流可能看起來像是一個激進(jìn)的范式切換(paradigm shift)。
但不要害怕,這個工作流實際上就是在功能分支工作流之上引入另一個抽象層。
不是直接通過單個中央倉庫來分享分支,而是把貢獻(xiàn)代碼發(fā)布到開發(fā)者自己的服務(wù)端倉庫中。
示例中解釋了,一個貢獻(xiàn)如何從一個開發(fā)者流到正式的master
分支中,但同樣的方法可以把貢獻(xiàn)集成到任一個倉庫中。
比如,如果團隊的幾個人協(xié)作實現(xiàn)一個功能,可以在開發(fā)之間用相同的方法分享變更,完全不涉及正式倉庫。
這使得Forking
工作流對于松散組織的團隊來說是個非常強大的工具。任一開發(fā)者可以方便地和另一開發(fā)者分享變更,任何分支都能有效地合并到正式代碼庫中。
#p#
2.5 Pull Requests
Pull requests
是Bitbucket
提供的讓開發(fā)者更方便地進(jìn)行協(xié)作的功能,提供了友好的Web
界面可以在提議的修改合并到正式項目之前對修改進(jìn)行討論。
開發(fā)者向團隊成員通知功能開發(fā)已經(jīng)完成,Pull Requests
是最簡單的用法。
開發(fā)者完成功能開發(fā)后,通過Bitbucket
賬號發(fā)起一個Pull Request
。
這樣讓涉及這個功能的所有人知道要去做Code Review
和合并到master
分支。
但是,Pull Request
遠(yuǎn)不止一個簡單的通知,而是為討論提交的功能的一個專門論壇。
如果變更有任何問題,團隊成員反饋在Pull Request
中,甚至push
新的提交微調(diào)功能。
所有的這些活動都直接跟蹤在Pull Request
中。
相比其它的協(xié)作模型,這種分享提交的形式有助于打造一個更流暢的工作流。
SVN
和Git
都能通過一個簡單的腳本收到通知郵件;但是,討論變更時,開發(fā)者通常只能去回復(fù)郵件。
這樣做會變得雜亂,尤其還要涉及后面的幾個提交時。
Pull Requests
把所有相關(guān)功能整合到一個和Bitbucket
倉庫界面集成的用戶友好Web
界面中。
2.5.1 解析Pull Request
當(dāng)要發(fā)起一個Pull Request
,你所要做的就是請求(Request
)另一個開發(fā)者(比如項目的維護(hù)者)
來pull
你倉庫中一個分支到他的倉庫中。這意味著你要提供4個信息以發(fā)起Pull Request
:
源倉庫、源分支、目的倉庫、目的分支。
這幾值多數(shù)Bitbucket
都會設(shè)置上合適的缺省值。但取決你用的協(xié)作工作流,你的團隊可能會要指定不同的值。
上圖顯示了一個Pull Request
請求合并一個功能分支到正式的master
分支上,但可以有多種不同的Pull Request
用法。
2.5.2 工作方式
Pull Request
可以和功能分支工作流、Gitflow
工作流或Forking
工作流一起使用。
但一個Pull Request
要求要么分支不同要么倉庫不同,所以不能用于集中式工作流。
在不同的工作流中使用Pull Request
會有一些不同,但基本的過程是這樣的:
-
開發(fā)者在本地倉庫中新建一個專門的分支開發(fā)功能。
-
開發(fā)者
push
分支修改到公開的Bitbucket
倉庫中。 -
開發(fā)者通過
Bitbucket
發(fā)起一個Pull Request
。 -
團隊的其它成員
review
code
,討論并修改。 -
項目維護(hù)者合并功能到官方倉庫中并關(guān)閉
Pull Request
。
本文后面內(nèi)容說明,Pull Request
在不同協(xié)作工作流中如何應(yīng)用。
2.5.3 在功能分支工作流中使用Pull Request
功能分支工作流用一個共享的Bitbucket
倉庫來管理協(xié)作,開發(fā)者在專門的分支上開發(fā)功能。
但不是立即合并到master
分支上,而是在合并到主代碼庫之前開發(fā)者應(yīng)該開一個Pull Request
發(fā)起功能的討論。
功能分支工作流只有一個公開的倉庫,所以Pull Request
的目的倉庫和源倉庫總是同一個。
通常開發(fā)者會指定他的功能分支作為源分支,master
分支作為目的分支。
收到Pull Request
后,項目維護(hù)者要決定如何做。如果功能沒問題,就簡單地合并到master
分支,關(guān)閉Pull Request
。
但如果提交的變更有問題,他可以在Pull Request
中反饋。之后新加的提交也會評論之后接著顯示出來。
在功能還沒有完全開發(fā)完的時候,也可能發(fā)起一個Pull Request
。
比如開發(fā)者在實現(xiàn)某個需求時碰到了麻煩,他可以發(fā)一個包含正在進(jìn)行中工作的Pull Request
。
其它的開發(fā)者可以在Pull Request
提供建議,或者甚至直接添加提交來解決問題。
2.5.4 在Gitflow
工作流中使用Pull Request
Gitflow
工作流和功能分支工作流類似,但圍繞項目發(fā)布定義一個嚴(yán)格的分支模型。
在Gitflow
工作流中使用Pull Request
讓開發(fā)者在發(fā)布分支或是維護(hù)分支上工作時,
可以有個方便的地方對關(guān)于發(fā)布分支或是維護(hù)分支的問題進(jìn)行交流。
Gitflow
工作流中Pull Request
的使用過程和上一節(jié)中完全一致:
當(dāng)一個功能、發(fā)布或是熱修復(fù)分支需要Review
時,開發(fā)者簡單發(fā)起一個Pull Request
,
團隊的其它成員會通過Bitbucket
收到通知。
新功能一般合并到develop
分支,而發(fā)布和熱修復(fù)則要同時合并到develop
分支和master
分支上。
Pull Request
可能用做所有合并的正式管理。
2.5.5 在Forking
工作流中使用Pull Request
在Forking
工作流中,開發(fā)者push
完成的功能到他自己的倉庫中,而不是共享倉庫。
然后,他發(fā)起一個Pull Request
,讓項目維護(hù)者知道他的功能已經(jīng)可以Review
了。
在這個工作流,Pull Request
的通知功能非常有用,
因為項目維護(hù)者不可能知道其它開發(fā)者在他們自己的倉庫添加了提交。
由于各個開發(fā)有自己的公開倉庫,Pull Request
的源倉庫和目標(biāo)倉庫不是同一個。
源倉庫是開發(fā)者的公開倉庫,源分支是包含了修改的分支。
如果開發(fā)者要合并修改到正式代碼庫中,那么目標(biāo)倉庫是正式倉庫,目標(biāo)分支是master
分支。
Pull Request
也可以用于正式項目之外的其它開發(fā)者之間的協(xié)作。
比如,如果一個開發(fā)者和一個團隊成員一起開發(fā)一個功能,他們可以發(fā)起一個Pull Request
,
用團隊成員的Bitbucket
倉庫作為目標(biāo),而不是正式項目的倉庫。
然后使用相同的功能分支作為源和目標(biāo)分支。
2個開發(fā)者之間可以在Pull Request
中討論和開發(fā)功能。
完成開發(fā)后,他們可以發(fā)起另一個Pull Request
,請求合并功能到正式的master
分支。
在Forking
工作流中,這樣的靈活性讓Pull Request
成為一個強有力的協(xié)作工具。
2.5.6 示例
下面的示例演示了Pull Request
如何在在Forking
工作流中使用。
也同樣適用于小團隊的開發(fā)協(xié)作和第三方開發(fā)者向開源項目的貢獻(xiàn)。
在示例中,小紅是個開發(fā),小明是項目維護(hù)者。他們各自有一個公開的Bitbucket
倉庫,而小明的倉庫包含了正式工程。
小紅fork
正式項目
小紅先要fork
小明的Bitbucket
倉庫,開始項目的開發(fā)。她登陸Bitbucket
,瀏覽到小明的倉庫頁面,
點Fork
按鈕。
然后為fork
出來的倉庫填寫名字和描述,這樣小紅就有了服務(wù)端的項目拷貝了。
小紅克隆她的Bitbucket
倉庫
下一步,小紅克隆自己剛才fork
出來的Bitbucket
倉庫,以在本機上準(zhǔn)備出工作拷貝。命令如下:
git clone https://user@bitbucket.org/user/repo.git
請記住,git clone
會自動創(chuàng)建origin
遠(yuǎn)程別名,是指向小紅fork
出來的倉庫。
小紅開發(fā)新功能
在開始改代碼前,小紅要為新功能先新建一個新分支。她會用這個分支作為Pull Request
的源分支。
git checkout -b some-feature
# 編輯代碼
git commit -a -m "Add first draft of some feature"
在新功能分支上,小紅按需要添加提交。甚至如果小紅覺得功能分支上的提交歷史太亂了,她可以用交互式rebase
來刪除或壓制提交。
對于大型項目,整理功能分支的歷史可以讓項目維護(hù)者更容易看出在Pull Request
中做了什么內(nèi)容。
小紅push
功能到她的Bitbucket
倉庫中
小紅完成了功能后,push
功能到她自己的Bitbucket
倉庫中(不是正式倉庫),用下面簡單的命令:
git push origin some-branch
這時她的變更可以讓項目維護(hù)者看到了(或者任何想要看的協(xié)作者)。
小紅發(fā)起Pull Request
Bitbucket
上有了她的功能分支后,小紅可以用她的Bitbucket
賬號瀏覽到她的fork
出來的倉庫頁面,
點右上角的【Pull Request
】按鈕,發(fā)起一個Pull Request
。
彈出的表單自動設(shè)置小紅的倉庫為源倉庫,詢問小紅以指定源分支、目標(biāo)倉庫和目標(biāo)分支。
小紅想要合并功能到正式倉庫,所以源分支是她的功能分支,目標(biāo)倉庫是小明的公開倉庫,
而目標(biāo)分支是master
分支。另外,小紅需要提供Pull Request
的標(biāo)題和描述信息。
如果需要小明以外的人審核批準(zhǔn)代碼,她可以把這些人填在【Reviewers】文本框中。
創(chuàng)建好了Pull Request
,通知會通過Bitbucket
系統(tǒng)消息或郵件(可選)發(fā)給小明。
小明review Pull Request
在小明的Bitbucket
倉庫頁面的【Pull Request
】Tab可以看到所有人發(fā)起的Pull Request
。
點擊小紅的Pull Request
會顯示出Pull Request
的描述、功能的提交歷史和每個變更的差異(diff
)。
如果小明想要合并到項目中,只要點一下【Merge
】按鈕,就可以同意Pull Request
并合并到master
分支。
但如果像這個示例中一樣小明發(fā)現(xiàn)了在小紅的代碼中的一個小Bug
,要小紅在合并前修復(fù)。
小明可以在整個Pull Request
上加上評注,或是選擇歷史中的某個提交加上評注。
小紅補加提交
如果小紅對反饋有任何疑問,可以在Pull Request
中響應(yīng),把Pull Request
當(dāng)作是她功能討論的論壇。
小紅在她的功能分支新加提交以解決代碼問題,并push
到她的Bitbucket
倉庫中,就像前一輪中的做法一樣。
這些提交會進(jìn)入的Pull Request
,小明在原來的評注旁邊可以再次review
變更。
小明接受Pull Request
最終,小明接受變更,合并功能分支到master
分支,并關(guān)閉Pull Request
。
至此,功能集成到項目中,其它的項目開發(fā)者可以用標(biāo)準(zhǔn)的git pull
命令pull
這些變更到自己的本地倉庫中。
到了這里,你應(yīng)該有了所有需要的工具來集成Pull Request
到你自己的工作流。
請記住,Pull Request
并不是為了替代任何 基于
Git的協(xié)作工作流
,
而是它們的一個便利的補充,讓團隊成員間的協(xié)作更輕松方便。
文章第一時間更新在github上,歡迎大家閱讀查看 https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md