我的在學習git工做流的過程當中,從原有的 SVN 模式很難徹底理解git的協做模式,直到有一天我看到了下面的文章,好多遺留在心中的困惑迎刃而解,因而我將這部分資料進行整理放到了github上,歡迎star查看最新更新內容, https://github.com/xirong/my-...css
咱們以使用SVN的工做流來使用git有什麼不妥? git 方便的branch在哪裏,團隊多人如何協做?衝突了怎麼辦?如何進行發佈控制? 經典的master-發佈、develop-主開發、hotfix-不過修復如何避免代碼不通過驗證上線? 如何在github上面與他人一塊兒協做,star-fork-pull request是怎樣的流程?
我我的很感激這篇文章,因此進行了整理,但願能幫到更多的人。整篇文章由 xirong 整理自 oldratlee 的github,方便統一的學習回顧,在此感謝下面兩位的貢獻。python
原文連接:Git Workflows and Tutorials
簡體中文:由 oldratlee 翻譯在 github 上 git-workflows-and-tutorials
1、譯序git
工做流其實不是一個初級主題,背後的本質問題實際上是有效的項目流程管理和高效的開發協同約定,不只是Git或SVN等VCS或SCM工具的使用。github
這篇指南以你們在SVN中已經廣爲熟悉使用的集中式工做流做爲起點,按部就班地演進到其它高效的分佈式工做流,還介紹瞭如何配合使用便利的Pull Request功能,體系地講解了各類工做流的應用。安全
行文中實踐原則和操做示例並重,對於Git的資深玩家能夠梳理思考提高,而新接觸的同窗,也能夠跟着step-by-step操做來操練學習並在實際工做中上手使用。服務器
關於Git工做流主題,網上體系的中文資料很少,主要是零散的操做說明,但願這篇文章能讓你更深刻理解並在工做中靈活有效地使用起來。併發
PS:app
文中Pull Request的介紹用的是Bitbucket代碼託管服務,因爲和GitHub基本同樣,若是你用的是GitHub(我本身也主要使用GitHub託管代碼),不影響理解和操做。python爬蟲
PPS:框架
本指南按部就班地講解工做流,若是Git用的很少,能夠從前面的講的工做流開始操練。操做過程去感覺指南的講解:解決什麼問題、如何解決問題,這樣理解就深了,也方便活用。
Gitflow工做流是經典模型,體現了工做流的經驗和精髓。隨着項目過程複雜化,會感覺到這個工做流中深思熟慮和威力!
Forking工做流是協做的(GitHub風格)能夠先看看Github的Help:Fork A Repo和Using pull requests 。照着操做,給一個Github項目貢獻你的提交,有操做經驗再看指南容易意會。指南中給了本身實現Fork的方法:Fork就是服務端的克隆。在指南的操練中使用代碼託管服務(如GitHub、Bitbucket),能夠點一下按鈕就讓開發者完成倉庫的fork操做。
本身理解粗淺,翻譯中不足和不對之處,歡迎建議(提交Issue)和指正(Fork後提交代碼)!
2、Git工做流指南
工做流有各式各樣的用法,但也正所以使得在實際工做中如何上手使用變得很頭大。這篇指南經過總覽公司團隊中最經常使用的幾種Git工做流讓你們能夠上手使用。
在閱讀的過程當中請記住,本文中的幾種工做流是做爲方案指導而不是條例規定。在展現了各類工做流可能的用法後,你能夠從不一樣的工做流中挑選或揉合出一個知足你本身需求的工做流。
2.1 集中式工做流
若是你的開發團隊成員已經很熟悉Subversion,集中式工做流讓你無需去適應一個全新流程就能夠體驗Git帶來的收益。這個工做流也能夠做爲向更Git風格工做流遷移的友好過渡。
轉到分佈式版本控制系統看起來像個使人生畏的任務,但不改變已用的工做流你也能夠用上Git帶來的收益。團隊能夠用和Subversion徹底不變的方式來開發項目。
但使用Git增強開發的工做流,Git有相比SVN的幾個優點。
首先,每一個開發能夠有屬於本身的整個工程的本地拷貝。隔離的環境讓各個開發者的工做和項目的其餘部分修改獨立開來 ——
即自由地提交到本身的本地倉庫,先徹底忽略上游的開發,直到方便的時候再把修改反饋上去。
其次,Git提供了強壯的分支和合並模型。不像SVN,Git的分支設計成能夠作爲一種用來在倉庫之間集成代碼和分享修改的『失敗安全』的機制。
2.1.1 工做方式
像Subversion同樣,集中式工做流以中央倉庫做爲項目全部修改的單點實體。相比SVN缺省的開發分支trunk,Git叫作master,全部修改提交到這個分支上。本工做流只用到master這一個分支。
開發者開始先克隆中央倉庫。在本身的項目拷貝中像SVN同樣的編輯文件和提交修改;但修改是存在本地的,和中央倉庫是徹底隔離的。開發者能夠把和上游的同步延後到一個方便時間點。
要發佈修改到正式項目中,開發者要把本地master分支的修改『推』到中央倉庫中。這至關於svn commit操做,但push操做會把全部還不在中央倉庫的本地提交都推上去。
2.1.2 衝突解決
中央倉庫表明了正式項目,因此提交歷史應該被尊重且是穩定不變的。若是開發者本地的提交歷史和中央倉庫有分歧,Git會拒絕push提交不然會覆蓋已經在中央庫的正式提交。
在開發者提交本身功能修改到中央庫前,須要先fetch在中央庫的新增提交,rebase本身提交到中央庫提交歷史之上。
這樣作的意思是在說,『我要把本身的修改加到別人已經完成的修改上。』最終的結果是一個完美的線性歷史,就像之前的SVN的工做流中同樣。
若是本地修改和上游提交有衝突,Git會暫停rebase過程,給你手動解決衝突的機會。Git解決合併衝突,用和生成提交同樣的git status和git add命令,很一致方便。還有一點,若是解決衝突時遇到麻煩,Git能夠很簡單停止整個rebase操做,重來一次(或者讓別人來幫助解決)。
2.1.3 示例
讓咱們一塊兒逐步分解來看看一個常見的小團隊如何用這個工做流來協做的。有兩個開發者小明和小紅,看他們是如何開發本身的功能並提交到中央倉庫上的。
有人先初始化好中央倉庫
第一步,有人在服務器上建立好中央倉庫。若是是新項目,你能夠初始化一個空倉庫;不然你要導入已有的Git或SVN倉庫。
中央倉庫應該是個裸倉庫(bare repository),即沒有工做目錄(working directory)的倉庫。能夠用下面的命令建立:
ssh user@host git init --bare /path/to/repo.git
確保寫上有效的user(SSH的用戶名),host(服務器的域名或IP地址),/path/to/repo.git(你想存放倉庫的位置)。
注意,爲了表示是一個裸倉庫,按照約定加上.git擴展名到倉庫名上。
全部人克隆中央倉庫
下一步,各個開發者建立整個項目的本地拷貝。經過git clone命令完成:
git clone ssh://user@host/path/to/repo.git
基於你後續會持續和克隆的倉庫作交互的假設,克隆倉庫時Git會自動添加遠程別名origin指回『父』倉庫。
小明開發功能
在小明的本地倉庫中,他使用標準的Git過程開發功能:編輯、暫存(Stage)和提交。
若是你不熟悉暫存區(Staging Area),這裏說明一下:暫存區的用來準備一個提交,但能夠不用把工做目錄中全部的修改內容都包含進來。
這樣你能夠建立一個高度聚焦的提交,儘管你本地修改不少內容。
git status # 查看本地倉庫的修改狀態 git add # 暫存文件 git commit # 提交文件
請記住,由於這些命令生成的是本地提交,小明能夠按本身需求反覆操做屢次,而不用擔憂中央倉庫上有了什麼操做。
對須要多個更簡單更原子分塊的大功能,這個作法是頗有用的。
小紅開發功能
與此同時,小紅在本身的本地倉庫中用相同的編輯、暫存和提交過程開發功能。和小明同樣,她也不關心中央倉庫有沒有新提交;
固然更不關心小明在他的本地倉庫中的操做,由於全部本地倉庫都是私有的。
小明發布功能
一旦小明完成了他的功能開發,會發布他的本地提交到中央倉庫中,這樣其它團隊成員能夠看到他的修改。他能夠用下面的git push命令:
git push origin master
注意,origin是在小明克隆倉庫時Git建立的遠程中央倉庫別名。master參數告訴Git推送的分支。
因爲中央倉庫自從小明克隆以來尚未被更新過,因此push操做不會有衝突,成功完成。
小紅試着發佈功能
一塊兒來看看在小明發布修改後,小紅push修改會怎麼樣?她使用徹底同樣的push命令:
git push origin master
但她的本地歷史已經和中央倉庫有分岐了,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操做要同步中央倉庫中別人修改時,提交歷史會以一個多餘的『合併提交』結尾。
對於集中式工做流,最好是使用rebase而不是生成一個合併提交。
小紅解決合併衝突
rebase操做過程是把本地提交一次一個地遷移到更新了的中央倉庫master分支之上。
這意味着可能要解決在遷移某個提交時出現的合併衝突,而不是解決包含了全部提交的大型合併時所出現的衝突。
這樣的方式讓你儘量保持每一個提交的聚焦和項目歷史的整潔。反過來,簡化了哪裏引入Bug的分析,若是有必要,回滾修改也能夠作到對項目影響最小。
若是小紅和小明的功能是相關的,不大可能在rebase過程當中有衝突。若是有,Git在合併有衝突的提交處暫停rebase過程,輸出下面的信息並帶上相關的指令:
CONFLICT (content): Merge conflict in <some-file>
Git很讚的一點是,任何人能夠解決他本身的衝突。在這個例子中,小紅能夠簡單的運行git status命令來查看哪裏有問題。
衝突文件列在Unmerged paths(未合併路徑)一節中:
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會繼續一個一個地合併後面的提交,如其它的提交有衝突就重複這個過程。
若是你碰到了衝突,但發現搞不定,不要驚慌。只要執行下面這條命令,就能夠回到你執行git pull --rebase命令前的樣子:
git rebase --abort
小紅成功發佈功能
小紅完成和中央倉庫的同步後,就能成功發佈她的修改了:
git push origin master
如你所見,僅使用幾個Git命令咱們就能夠模擬出傳統Subversion開發環境。對於要從SVN遷移過來的團隊來講這太好了,但沒有發揮出Git分佈式本質的優點。
若是你的團隊適應了集中式工做流,但想要更流暢的協做效果,絕對值得探索一下 功能分支工做流 的收益。
經過爲一個功能分配一個專門的分支,可以作到一個新增功能集成到正式項目以前對新功能進行深刻討論。
2.2 功能分支工做流
功能分支工做流以集中式工做流爲基礎,不一樣的是爲各個新功能分配一個專門的分支來開發。這樣能夠在把新功能集成到正式項目前,用Pull Requests的方式討論變動。
一旦你玩轉了集中式工做流,在開發過程當中能夠很簡單地加上功能分支,用來鼓勵開發者之間協做和簡化交流。
功能分支工做流背後的核心思路是全部的功能開發應該在一個專門的分支,而不是在master分支上。
這個隔離能夠方便多個開發者在各自的功能上開發而不會弄亂主幹代碼。
另外,也保證了master分支的代碼必定不會是有問題的,極大有利於集成環境。
功能開發隔離也讓pull requests工做流成功可能,
pull requests工做流能爲每一個分支發起一個討論,在分支合入正式項目以前,給其它開發者有表示贊同的機會。
另外,若是你在功能開發中有問題卡住了,能夠開一個pull requests來向同窗們徵求建議。
這些作法的重點就是,pull requests讓團隊成員之間互相評論工做變成很是方便!
2.2.1 工做方式
功能分支工做流仍然用中央倉庫,而且master分支仍是表明了正式項目的歷史。
但不是直接提交本地歷史到各自的本地master分支,開發者每次在開始新功能前先建立一個新分支。
功能分支應該有個有描述性的名字,好比animated-menu-items或issue-#1061,這樣可讓分支有個清楚且高聚焦的用途。
在master分支和功能分支之間,Git是沒有技術上的區別,因此開發者能夠用和集中式工做流中徹底同樣的方式編輯、暫存和提交修改到功能分支上。
另外,功能分支也能夠(且應該)push到中央倉庫中。這樣不修改正式代碼就能夠和其它開發者分享提交的功能。
因爲master僅有的一個『特殊』分支,在中央倉庫上存多個功能分支不會有任何問題。固然,這樣作也能夠很方便地備份各自的本地提交。
2.2.2 Pull Requests
功能分支除了能夠隔離功能的開發,也使得經過Pull Requests討論變動成爲可能。
一旦某個開發完成一個功能,不是當即合併到master,而是push到中央倉庫的功能分支上併發起一個Pull Request請求去合併修改到master。
在修改爲爲主幹代碼前,這讓其它的開發者有機會先去Review變動。
Code Review是Pull Requests的一個重要的收益,但Pull Requests目的是討論代碼一個通用方式。
你能夠把Pull Requests做爲專門給某個分支的討論。這意味着能夠在更早的開發過程當中就能夠進行Code Review。
好比,一個開發者開發功能須要幫助時,要作的就是發起一個Pull Request,相關的人就會自動收到通知,在相關的提交旁邊能看到須要幫助解決的問題。
一旦Pull Request被接受了,發佈功能要作的就和集中式工做流就很像了。
首先,肯定本地的master分支和上游的master分支是同步的。而後合併功能分支到本地master分支並push已經更新的本地master分支到中央倉庫。
倉庫管理的產品解決方案像Bitbucket或Stash,能夠良好地支持Pull Requests。能夠看看Stash的Pull Requests文檔。
2.2.3 示例
下面的示例演示瞭如何把Pull Requests做爲Code Review的方式,但注意Pull Requests能夠用於不少其它的目的。
小紅開始開發一個新功能
在開始開發功能前,小紅須要一個獨立的分支。使用下面的命令新建一個分支:
git checkout -b marys-feature master
這個命令檢出一個基於master名爲marys-feature的分支,Git的-b選項表示若是分支還不存在則新建分支。
這個新分支上,小紅按老套路編輯、暫存和提交修改,按須要提交以實現功能:
git status git add <some-file> git commit
小紅要去吃個午餐
早上小紅爲新功能添加一些提交。
去吃午餐前,push功能分支到中央倉庫是很好的作法,這樣能夠方便地備份,若是和其它開發協做,也讓他們能夠看到小紅的提交。
git push -u origin marys-feature
這條命令push marys-feature分支到中央倉庫(origin),-u選項設置本地分支去跟蹤遠程對應的分支。
設置好跟蹤的分支後,小紅就可使用git push命令省去指定推送分支的參數。
小紅完成功能開發
小紅吃完午餐回來,完成整個功能的開發。在合併到master以前,
她發起一個Pull Request讓團隊的其它人知道功能已經完成。但首先,她要確認中央倉庫中已經有她最近的提交:
git push
而後,在她的Git GUI客戶端中發起Pull Request,請求合併marys-feature到master,團隊成員會自動收到通知。
Pull Request很酷的是能夠在相關的提交旁邊顯示評註,因此你能夠很對某個變動集提問。
小黑收到Pull Request
小黑收到了Pull Request後會查看marys-feature的修改。決定在合併到正式項目前是否要作些修改,且經過Pull Request和小紅來回地討論。
小紅再作修改
要再作修改,小紅用和功能第一個迭代徹底同樣的過程。編輯、暫存、提交併push更新到中央倉庫。小紅這些活動都會顯示在Pull Request上,小黑能夠斷續作評註。
若是小黑有須要,也能夠把marys-feature分支拉到本地,本身來修改,他加的提交也會同樣顯示在Pull Request上。
小紅髮布她的功能
一旦小黑能夠的接受Pull Request,就能夠合併功能到穩定項目代碼中(能夠由小黑或是小紅來作這個操做):
git checkout master git pull git pull origin marys-feature git push
不管誰來作合併,首先要檢出master分支並確認是它是最新的。而後執行git pull origin marys-feature合併marys-feature分支到和已經和遠程一致的本地master分支。
你可使用簡單git merge marys-feature命令,但前面的命令能夠保證老是最新的新功能分支。
最後更新的master分支要從新push回到origin。
這個過程經常會生成一個合併提交。有些開發者喜歡有合併提交,由於它像一個新功能和原來代碼基線的連通符。
但若是你偏心線性的提交歷史,能夠在執行合併時rebase新功能到master分支的頂部,這樣生成一個快進(fast-forward)的合併。
一些GUI客戶端能夠只要點一下『接受』按鈕執行好上面的命令來自動化Pull Request接受過程。
若是你的不能這樣,至少在功能合併到master分支後能自動關閉Pull Request。
與此同時,小明在作和小紅同樣的事
當小紅和小黑在marys-feature上工做並討論她的Pull Request的時候,小明在本身的功能分支上作徹底同樣的事。
經過隔離功能到獨立的分支上,每一個人均可以自主的工做,固然必要的時候在開發者之間分享變動仍是比較繁瑣的。
到了這裏,希望你發現了功能分支能夠很直接地在 集中式工做流 的僅有的master分支上完成多功能的開發。
另外,功能分支還使用了Pull Request,使得能夠在你的版本控制GUI客戶端中討論某個提交。
功能分支工做流是開發項目異常靈活的方式。問題是,有時候太靈活了。對於大型團隊,經常須要給不一樣分支分配一個更具體的角色。
Gitflow工做流是管理功能開發、發佈準備和維護的經常使用模式。
2.3 Gitflow工做流
Gitflow工做流經過爲功能開發、發佈準備和維護分配獨立的分支,讓發佈迭代過程更流暢。嚴格的分支模型也爲大型項目提供了一些很是必要的結構。
這節介紹的Gitflow工做流借鑑自在nvie的Vincent Driessen。
Gitflow工做流定義了一個圍繞項目發佈的嚴格分支模型。雖然比功能分支工做流複雜幾分,但提供了用於一個健壯的用於管理大型項目的框架。
Gitflow工做流沒有用超出功能分支工做流的概念和命令,而是爲不一樣的分支分配一個很明確的角色,並定義分支之間如何和何時進行交互。
除了使用功能分支,在作準備、維護和記錄發佈也使用各自的分支。
固然你能夠用上功能分支工做流全部的好處:Pull Requests、隔離實驗性開發和更高效的協做。
2.3.1 工做方式
Gitflow工做流仍然用中央倉庫做爲全部開發者的交互中心。和其它的工做流同樣,開發者在本地工做並push分支到要中央倉庫中。
2.3.2 歷史分支
相對使用僅有的一個master分支,Gitflow工做流使用2個分支來記錄項目的歷史。master分支存儲了正式發佈的歷史,而develop分支做爲功能的集成分支。
這樣也方便master分支上的全部提交分配一個版本號。
剩下要說明的問題圍繞着這2個分支的區別展開。
2.3.3 功能分支
每一個新功能位於一個本身的分支,這樣能夠push到中央倉庫以備份和協做。
但功能分支不是從master分支上拉出新分支,而是使用develop分支做爲父分支。當新功能完成時,合併回develop分支。
新功能提交應該從不直接與master分支交互
注意,從各類含義和目的上來看,功能分支加上develop分支就是功能分支工做流的用法。但Gitflow工做流沒有在這裏止步。
2.3.4 發佈分支
一旦develop分支上有了作一次發佈(或者說快到了既定的發佈日)的足夠功能,就從develop分支上fork一個發佈分支。
新建的分支用於開始發佈循環,因此從這個時間點開始以後新的功能不能再加到這個分支上——
這個分支只應該作Bug修復、文檔生成和其它面向發佈任務。
一旦對外發布的工做都完成了,發佈分支合併到master分支並分配一個版本號打好Tag。
另外,這些重新建發佈分支以來的作的修改要合併回develop分支。
使用一個用於發佈準備的專門分支,使得一個團隊能夠在完善當前的發佈版本的同時,另外一個團隊能夠繼續開發下個版本的功能。
這也打造定義良好的開發階段(好比,能夠很輕鬆地說,『這周咱們要作準備發佈版本4.0』,而且在倉庫的目錄結構中能夠實際看到)。
經常使用的分支約定:
用於新建發佈分支的分支: develop
用於合併的分支: master
分支命名: release- 或 release/
2.3.5 維護分支
維護分支或說是熱修復(hotfix)分支用於生成快速給產品發佈版本(production releases)打補丁,這是惟一能夠直接從master分支fork出來的分支。
修復完成,修改應該立刻合併回master分支和develop分支(當前的發佈分支),master分支應該用新的版本號打好Tag。
爲Bug修復使用專門分支,讓團隊能夠處理掉問題而不用打斷其它工做或是等待下一個發佈循環。
你能夠把維護分支想成是一個直接在master分支上處理的臨時發佈。
2.3.6 示例
下面的示例演示本工做流如何用於管理單個發佈循環。假設你已經建立了一箇中央倉庫。
建立開發分支
第一步爲master分支配套一個develop分支。簡單來作能夠本地建立一個空的develop分支,push到服務器上:
git branch develop
git push -u origin develop
之後這個分支將會包含了項目的所有歷史,而master分支將只包含了部分歷史。其它開發者這時應該克隆中央倉庫,建好develop分支的跟蹤分支:
git clone ssh://user@host/path/to/repo.git git checkout -b develop origin/develop
如今每一個開發都有了這些歷史分支的本地拷貝。
小紅和小明開始開發新功能
這個示例中,小紅和小明開始各自的功能開發。他們須要爲各自的功能建立相應的分支。新分支不是基於master分支,而是應該基於develop分支:
git checkout -b some-feature develop
他們用老套路添加提交到各自功能分支上:編輯、暫存、提交:
git status git add <some-file> git commit
小紅完成功能開發
添加了提交後,小紅以爲她的功能OK了。若是團隊使用Pull Requests,這時候能夠發起一個用於合併到develop分支。
不然她能夠直接合併到她本地的develop分支後push到中央倉庫:
git pull origin develop
git checkout develop
git merge some-feature
git push
git branch -d some-feature
第一條命令在合併功能前確保develop分支是最新的。注意,功能決不該該直接合併到master分支。
衝突解決方法和集中式工做流同樣。
小紅開始準備發佈
這個時候小明正在實現他的功能,小紅開始準備她的第一個項目正式發佈。
像功能開發同樣,她用一個新的分支來作發佈準備。這一步也肯定了發佈的版本號:
git checkout -b release-0.1 develop
這個分支是清理髮布、執行全部測試、更新文檔和其它爲下個發佈作準備操做的地方,像是一個專門用於改善發佈的功能分支。
只要小紅建立這個分支並push到中央倉庫,這個發佈就是功能凍結的。任何不在develop分支中的新功能都推到下個發佈循環中。
小紅完成發佈
一旦準備好了對外發布,小紅合併修改到master分支和develop分支上,刪除發佈分支。合併回develop分支很重要,由於在發佈分支中已經提交的更新須要在後面的新功能中也要是可用的。
另外,若是小紅的團隊要求Code Review,這是一個發起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
發佈分支是做爲功能開發(develop分支)和對外發布(master分支)間的緩衝。只要有合併到master分支,就應該打好Tag以方便跟蹤。
git tag -a 0.1 -m "Initial public release" master
git push --tags
Git有提供各類勾子(hook),即倉庫有事件發生時觸發執行的腳本。
能夠配置一個勾子,在你push中央倉庫的master分支時,自動構建好對外發布。
最終用戶發現Bug
對外發布後,小紅回去和小明一塊兒作下個發佈的新功能開發,直到有最終用戶開了一個Ticket抱怨當前版本的一個Bug。
爲了處理Bug,小紅(或小明)從master分支上拉出了一個維護分支,提交修改以解決問題,而後直接合並回master分支:
git checkout -b issue-#001 master
Fix the bug
git checkout master
git merge issue-#001
git push
就像發佈分支,維護分支中新加這些重要修改須要包含到develop分支中,因此小紅要執行一個合併操做。而後就能夠安全地刪除這個分支了:
git checkout develop git merge issue-#001 git push git branch -d issue-#001
到了這裏,希望你對集中式工做流、功能分支工做流和Gitflow工做流已經感受很溫馨了。
你應該也牢固的掌握了本地倉庫的潛能,push/pull模式和Git健壯的分支和合並模型。
記住,這裏演示的工做流只是可能用法的例子,而不是在實際工做中使用Git不可違逆的條例。
因此不要畏懼按本身須要對工做流的用法作取捨。不變的目標就是讓Git爲你所用。
2.4 Forking工做流
Forking工做流是分佈式工做流,充分利用了Git在分支和克隆上的優點。能夠安全可靠地管理大團隊的開發者(developer),並能接受不信任貢獻者(contributor)的提交。
Forking工做流和前面討論的幾種工做流有根本的不一樣,這種工做流不是使用單個服務端倉庫做爲『中央』代碼基線,而讓各個開發者都有一個服務端倉庫。這意味着各個代碼貢獻者有2個Git倉庫而不是1個:一個本地私有的,另外一個服務端公開的。
Forking工做流的一個主要優點是,貢獻的代碼能夠被集成,而不須要全部人都能push代碼到僅有的中央倉庫中。
開發者push到本身的服務端倉庫,而只有項目維護者才能push到正式倉庫。
這樣項目維護者能夠接受任何開發者的提交,但無需給他正式代碼庫的寫權限。
效果就是一個分佈式的工做流,能爲大型、自發性的團隊(包括了不受信的第三方)提供靈活的方式來安全的協做。
也讓這個工做流成爲開源項目的理想工做流。
2.4.1 工做方式
和其它的Git工做流同樣,Forking工做流要先有一個公開的正式倉庫存儲在服務器上。
但一個新的開發者想要在項目上工做時,不是直接從正式倉庫克隆,而是fork正式項目在服務器上建立一個拷貝。
這個倉庫拷貝做爲他我的公開倉庫 ——
其它開發者不容許push到這個倉庫,但能夠pull到修改(後面咱們很快就會看這點很重要)。
在建立了本身服務端拷貝以後,和以前的工做流同樣,開發者執行git clone命令克隆倉庫到本地機器上,做爲私有的開發環境。
要提交本地修改時,push提交到本身公開倉庫中 —— 而不是正式倉庫中。
而後,給正式倉庫發起一個pull request,讓項目維護者知道有更新已經準備好能夠集成了。
對於貢獻的代碼,pull request也能夠很方便地做爲一個討論的地方。
爲了集成功能到正式代碼庫,維護者pull貢獻者的變動到本身的本地倉庫中,檢查變動以確保不會讓項目出錯,
合併變動到本身本地的master分支,
而後pushmaster分支到服務器的正式倉庫中。
到此,貢獻的提交成爲了項目的一部分,其它的開發者應該執行pull操做與正式倉庫同步本身本地倉庫。
2.4.2 正式倉庫
在Forking工做流中,『官方』倉庫的叫法只是一個約定,理解這點很重要。
從技術上來看,各個開發者倉庫和正式倉庫在Git看來沒有任何區別。
事實上,讓正式倉庫之因此正式的惟一緣由是它是項目維護者的公開倉庫。
2.4.3 Forking工做流的分支使用方式
全部的我的公開倉庫實際上只是爲了方便和其它的開發者共享分支。
各個開發者應該用分支隔離各個功能,就像在功能分支工做流和Gitflow工做流同樣。
惟一的區別是這些分支被共享了。在Forking工做流中這些分支會被pull到另外一個開發者的本地倉庫中,而在功能分支工做流和Gitflow工做流中是直接被push到正式倉庫中。
2.4.4 示例
項目維護者初始化正式倉庫
和任何使用Git項目同樣,第一步是建立在服務器上一個正式倉庫,讓全部團隊成員均可以訪問到。
一般這個倉庫也會做爲項目維護者的公開倉庫。
公開倉庫應該是裸倉庫,無論是否是正式代碼庫。
因此項目維護者會運行像下面的命令來搭建正式倉庫:
ssh user@host
git init --bare /path/to/repo.git
Bitbucket和Stash提供了一個方便的GUI客戶端以完成上面命令行作的事。
這個搭建中央倉庫的過程和前面提到的工做流徹底同樣。
若是有現存的代碼庫,維護者也要push到這個倉庫中。
開發者fork正式倉庫
其它全部的開發須要fork正式倉庫。
能夠用git clone命令用SSH協議連通到服務器,
拷貝倉庫到服務器另外一個位置 —— 是的,fork操做基本上就只是一個服務端的克隆。
Bitbucket和Stash上能夠點一下按鈕就讓開發者完成倉庫的fork操做。
這一步完成後,每一個開發都在服務端有一個本身的倉庫。和正式倉庫同樣,這些倉庫應該是裸倉庫。
開發者克隆本身fork出來的倉庫
下一步,各個開發者要克隆本身的公開倉庫,用熟悉的git clone命令。
在這個示例中,假定用Bitbucket託管了倉庫。記住,若是這樣的話各個開發者須要有各自的Bitbucket帳號,
使用下面命令克隆服務端本身的倉庫:
git clone https://user@bitbucket.org/us...
相比前面介紹的工做流只用了一個origin遠程別名指向中央倉庫,Forking工做流須要2個遠程別名 ——
一個指向正式倉庫,另外一個指向開發者本身的服務端倉庫。別名的名字能夠任意命名,常見的約定是使用origin做爲遠程克隆的倉庫的別名
(這個別名會在運行git clone自動建立),upstream(上游)做爲正式倉庫的別名。
git remote add upstream https://bitbucket.org/maintainer/repo
須要本身用上面的命令建立upstream別名。這樣能夠簡單地保持本地倉庫和正式倉庫的同步更新。
注意,若是上游倉庫須要認證(好比不是開源的),你須要提供用戶:
git remote add upstream https://user@bitbucket.org/ma...
這時在克隆和pull正式倉庫時,須要提供用戶的密碼。
開發者開發本身的功能
在剛克隆的本地倉庫中,開發者能夠像其它工做流同樣的編輯代碼、提交修改和新建分支:
git checkout -b some-feature
Edit some code
git commit -a -m "Add first draft of some feature"
全部的修改都是私有的直到push到本身公開倉庫中。若是正式項目已經往前走了,能夠用git pull命令得到新的提交:
git pull upstream master
因爲開發者應該都在專門的功能分支上工做,pull操做結果會都是快進合併。
開發者發佈本身的功能
一旦開發者準備好了分享新功能,須要作二件事。
首先,經過push他的貢獻代碼到本身的公開倉庫中,讓其它的開發者均可以訪問到。
他的origin遠程別名應該已經有了,因此要作的就是:
git push origin feature-branch
這裏和以前的工做流的差別是,origin遠程別名指向開發者本身的服務端倉庫,而不是正式倉庫。
第二件事,開發者要通知項目維護者,想要合併他的新功能到正式庫中。
Bitbucket和Stash提供了Pull Request按鈕,彈出表單讓你指定哪一個分支要合併到正式倉庫。
通常你會想集成你的功能分支到上游遠程倉庫的master分支中。
項目維護者集成開發者的功能
當項目維護者收到pull request,他要作的是決定是否集成它到正式代碼庫中。有二種方式來作:
直接在pull request中查看代碼
pull代碼到他本身的本地倉庫,再手動合併
第一種作法更簡單,維護者能夠在GUI中查看變動的差別,作評註和執行合併。
但若是出現了合併衝突,須要第二種作法來解決。這種狀況下,維護者須要從開發者的服務端倉庫中fetch功能分支,
合併到他本地的master分支,解決衝突:
git fetch https://bitbucket.org/user/repo feature-branch
查看變動
git checkout master
git merge FETCH_HEAD
變動集成到本地的master分支後,維護者要push變動到服務器上的正式倉庫,這樣其它的開發者都能訪問到:
git push origin master
注意,維護者的origin是指向他本身公開倉庫的,便是項目的正式代碼庫。到此,開發者的貢獻徹底集成到了項目中。
開發者和正式倉庫作同步
因爲正式代碼庫往前走了,其它的開發須要和正式倉庫作同步:
git pull upstream master
若是你以前是使用SVN,Forking工做流可能看起來像是一個激進的範式切換(paradigm shift)。
但不要懼怕,這個工做流實際上就是在功能分支工做流之上引入另外一個抽象層。
不是直接經過單箇中央倉庫來分享分支,而是把貢獻代碼發佈到開發者本身的服務端倉庫中。
示例中解釋了,一個貢獻如何從一個開發者流到正式的master分支中,但一樣的方法能夠把貢獻集成到任一個倉庫中。
好比,若是團隊的幾我的協做實現一個功能,能夠在開發之間用相同的方法分享變動,徹底不涉及正式倉庫。
這使得Forking工做流對於鬆散組織的團隊來講是個很是強大的工具。任一開發者能夠方便地和另外一開發者分享變動,任何分支都能有效地合併到正式代碼庫中。
更過資源上就上:去轉盤,www.quzhuanpan.com,我創建了一個Q羣歡迎你們加入討論學習js,css,python爬蟲等技術(Q羣:512245829)。