分佈式是如何實現的:git
好處:github
開發者開始先克隆中央倉庫。在本身的項目拷貝中編輯文件和提交修改;但修改是存在本地的,和中央倉庫是徹底隔離的。開發者能夠把和上游的同步延後到一個方便時間點。框架
要發佈修改到正式項目中,開發者要把本地master分支的修改『推』到中央倉庫中,推送(push)操做會把全部還不在中央倉庫的本地提交都推上去。分佈式
中央倉庫表明了正式項目,因此提交歷史是穩定不變的。若是開發者本地的提交歷史和中央倉庫有分歧,Git會拒絕push提交。svn
在開發者提交本身功能修改到中央庫前,須要先拉取(fetch)在中央庫的新增提交,變基(rebase)本身提交到中央庫提交歷史之上。工具
這樣作的意思是在說,『我要把本身的修改加到別人已經完成的修改上。』最終的結果是一個完美的線性歷史。學習
若是本地修改和上游提交有衝突,Git會暫停rebase過程,給你手動解決衝突的機會。還有一點,若是解決衝突時遇到麻煩,Git能夠很簡單停止整個rebase操做,重來一次(或者讓別人來幫助解決)。測試
rebase操做過程是把本地提交一次一個地遷移到更新了的中央倉庫master分支之上。
這意味着可能要解決在遷移某個提交時出現的合併衝突,而不是解決包含了全部提交的大型合併時所出現的衝突。
這樣的方式讓你儘量保持每一個提交的聚焦和項目歷史的整潔。反過來,簡化了哪裏引入Bug的分析,若是有必要,回滾修改也能夠作到對項目影響最小。
讓咱們一塊兒逐步分解來看看一個常見的小團隊如何用這個工做流來協做的。有兩個開發者小明和小紅,看他們是如何開發本身的功能並提交到中央倉庫上的。
第一步,有人在服務器上建立好中央倉庫。
下一步,各個開發者建立整個項目的本地拷貝。
基於你後續會持續和克隆的倉庫作交互的假設,克隆倉庫時Git會自動添加遠程別名origin指回中央倉庫。
在小明的本地倉庫中,他使用標準的Git過程開發功能:編輯、暫存(Stage)和提交。
若是你不熟悉暫存區(Staging Area),這裏說明一下:暫存區的用來準備一個提交,但能夠不用把工做目錄中全部的修改內容都包含進來。
這樣你能夠建立一個高度聚焦的提交,即便你本地修改不少內容。
請記住,由於這些命令生成的是本地提交,小明能夠按本身需求反覆操做屢次,而不用擔憂中央倉庫上有了什麼操做。
對須要多個更簡單更原子分塊的大功能,這個作法是頗有用的。
與此同時,小紅在本身的本地倉庫中用相同的編輯、暫存和提交過程開發功能。和小明同樣,她也不關心中央倉庫有沒有新提交;
固然更不關心小明在他的本地倉庫中的操做,由於全部本地倉庫都是私有的。
一旦小明完成了他的功能開發,會發布他的本地提交到中央倉庫中,這樣其它團隊成員能夠看到他的修改。
因爲中央倉庫自從小明克隆以來尚未被更新過,因此推送(push)操做不會有衝突,成功完成。
一塊兒來看看在小明發布修改後,小紅push修改會怎麼樣?
但她的本地歷史已經和中央倉庫有分岐了,Git拒絕操做並給出下面很長的出錯消息:
這避免了小紅覆寫正式的提交。她要先獲取小明的更新到她的本地倉庫合併上她的本地修改後,再重試。
小紅獲取上游的修改到本身的倉庫中。
選擇要變基(衍合 rebase)的位置,這裏選擇的是origin/master,即變基到中央倉庫最新的master上。
若是小紅和小明的功能是不相關的,不大可能在rebase過程當中有衝突。
若是有,Git在合併有衝突的提交處暫停rebase過程,輸出下面的信息並帶上相關的指令:
本例中,小明上游先提交修改了"sdfghjkl!"-->"sdfghjkl1!",小紅後提交了修改"sdfghjkl!"-->"sdfghjkl2!"
小紅須要打開衝突的文件:
其中
<<<<< HEAD
上游提交修改
======
本次提交修改
>>>>>>>> *******
須要選擇使用什麼內容,好比說使用"sdfghjkl2!" ,則刪除其餘上游提交修改以及標識行
暫存修改,完成提交。
再次右鍵衍合(變基 rebase)
選擇繼續衍合,完成衍合(變基 rebase)過程。
變基完成後的結果以下圖
若是你忘了變基(rebase)操做,推送(pull)仍然能夠完成,切換到「文件狀態」格外進行一次合併提交,而後再推送。但每次推送(pull)操做要同步中央倉庫中別人修改時,提交歷史會以一個多餘的『合併提交』結尾。
最好是使用rebase而不是生成一個合併提交。
小紅完成和中央倉庫的同步後,就能成功發佈她的修改了。
說完了單個分支,下面將對功能分支工做流進行深刻討論
Gitflow工做流經過爲功能開發、發佈準備和維護分配獨立的分支,讓發佈迭代過程更流暢。嚴格的分支模型也爲大型項目提供了一些很是必要的結構。
Gitflow工做流定義了一個圍繞項目發佈的嚴格分支模型。雖然比功能分支工做流複雜幾分,但提供了用於一個強壯的用於管理大型項目的框架。
Gitflow工做流沒有用超出功能分支工做流的概念和命令,而是爲不一樣的分支分配一個很明確的角色,並定義分支之間如何和何時進行交互。
除了使用功能分支,在作準備、維護和記錄發佈也使用各自的分支。
固然你能夠用上功能分支工做流全部的好處:Pull Requests、隔離實驗性開發和更高效的協做。
Gitflow工做流仍然用中央倉庫做爲全部開發者的交互中心。和其它的工做流同樣,開發者在本地工做並push分支到要中央倉庫中。
相對使用僅有的一個master分支,Gitflow工做流使用2個分支來記錄項目的歷史。master分支存儲了正式發佈的歷史,而develop分支做爲功能的集成分支。
這樣也方便master分支上的全部提交分配一個版本號。
剩下要說明的問題圍繞着這2個分支的區別展開。
每一個新功能位於一個本身的分支,這樣能夠push到中央倉庫以備份和協做。
但功能分支不是從master分支上拉出新分支,而是使用develop分支做爲父分支。當新功能完成時,合併回develop分支。
新功能提交應該從不直接與master分支交互。
注意,從各類含義和目的上來看,功能分支加上develop分支就是功能分支工做流的用法。但Gitflow工做流沒有在這裏止步。
一旦develop分支上有了作一次發佈(或者說快到了既定的發佈日)的足夠功能,就從develop分支上fork一個發佈分支。
新建的分支用於開始發佈循環,因此從這個時間點開始以後新的功能不能再加到這個分支上——
這個分支只應該作Bug修復、文檔生成和其它面向發佈任務。
一旦對外發布的工做都完成了,發佈分支合併到master分支並分配一個版本號打好Tag。
另外,這些重新建發佈分支以來的作的修改要合併回develop分支。
使用一個用於發佈準備的專門分支,使得一個團隊能夠在完善當前的發佈版本的同時,另外一個團隊能夠繼續開發下個版本的功能。
這也打造定義良好的開發階段(好比,能夠很輕鬆地說,『這周咱們要作準備發佈版本4.0』,而且在倉庫的目錄結構中能夠實際看到)。
維護分支或說是熱修復(hotfix)分支用於生成快速給產品發佈版本(production releases)打補丁,這是惟一能夠直接從master分支fork出來的分支。
修復完成,修改應該立刻合併回master分支和develop分支(當前的發佈分支),master分支應該用新的版本號打好Tag。
爲Bug修復使用專門分支,讓團隊能夠處理掉問題而不用打斷其它工做或是等待下一個發佈循環。
你能夠把維護分支想成是一個直接在master分支上處理的臨時發佈。
下面的示例演示本工做流如何用於管理單個發佈循環。假設你已經建立了一箇中央倉庫。
第一步爲master分支配套一個develop分支。簡單來作能夠本地建立一個空的develop分支,push到服務器上
之後這個分支將會包含了項目的所有歷史,而master分支將只包含了部分歷史。其它開發者這時應該克隆中央倉庫,建好develop分支的跟蹤分支
如今每一個開發都有了這些歷史分支的本地拷貝。
這個示例中,小紅和小明開始各自的功能開發。他們須要爲各自的功能建立相應的分支。新分支不是基於master分支,而是應該基於develop分支:
後面的功能都在這裏,將再也不重複貼圖。
他們用老套路添加提交到各自功能分支上:編輯、暫存、提交
添加了提交後,小紅以爲她的功能OK了。她能夠直接合併到她本地的develop分支後push到中央倉庫:
獲取,更新develop分支狀態(切換到develop分支,拉取),點擊git工做流,完成功能,推送。
在合併功能前確保develop分支是最新的。注意,功能決不該該直接合併到master分支。
衝突解決方法和集中式工做流同樣。
這個時候小明正在實現他的功能,小紅開始準備她的第一個項目正式發佈。
像功能開發同樣,她用一個新的分支來作發佈準備。
這個分支是清理髮布、執行全部測試、更新文檔和其它爲下個發佈作準備操做的地方,像是一個專門用於改善發佈的功能分支。
只要小紅建立這個分支並push到中央倉庫,這個發佈就是功能凍結的。任何不在develop分支中的新功能都推到下個發佈循環中。
一旦準備好了對外發布,小紅合併修改到master分支和develop分支上,刪除發佈分支。合併回develop分支很重要,由於在發佈分支中已經提交的更新須要在後面的新功能中也要是可用的。
發佈分支是做爲功能開發(develop分支)和對外發布(master分支)間的緩衝。只要有合併到master分支,就應該打好Tag以方便跟蹤。
對外發布後,小紅回去和小明一塊兒作下個發佈的新功能開發,直到有最終用戶開了一個Ticket抱怨當前版本的一個Bug。
爲了處理Bug,小紅(或小明)從master分支上拉出了一個維護分支,提交修改以解決問題,而後直接合並回master分支。
就像發佈分支,維護分支中新加這些重要修改須要包含到develop分支中,因此小紅要執行一個合併操做。而後就能夠安全地刪除這個分支了。
到了這裏,希望你對集中式工做流、功能分支工做流和Gitflow工做流已經感受很溫馨了。
你應該也牢固的掌握了本地倉庫的潛能,push/pull模式和Git的分支和合並模型。
記住,這裏演示的工做流只是可能用法的例子,而不是在實際工做中使用Git不可違逆的條例。
因此不要畏懼按本身須要對工做流的用法作取捨。不變的目標就是讓Git爲你所用。
獲取是從中央倉庫檢查分支是否有更新。若是有更新,則獲得更新的詳細信息,如提交信息,變動差別等等。
拉取是將中央倉庫與本地倉庫進行同步,將差別同步到本地。
丟棄是指將修改的部分丟棄,即恢復到修改前的狀態。
移除是指刪除這個文件,若是以前沒有提交過這個文件,移除後將沒法找回該文件。
忽略是指再也不對該文件進行差別檢查和提交。忽略會在.ignore文件中增長一項,同步到中央倉庫,這樣,全部環境都將忽略該文件。若是該文件已經在提交歷史中,該文件不會被刪除。
建立高度聚焦的提交,方便查看檢索,提交信息格式:功能名稱--新增/修復--描述