git相關的文章和教程很是多,可是系統介紹和了解工做流的人並很少,在使用過程當中用錯或用偏的也很多,這裏分享的是,假設你已經入門的狀況下,咱們如何去選擇適合團隊須要的工做流。html
git優點
這裏先嘮叨git的優點,對比傳統的代碼管理工具,git至少有如下這些優勢:git
- 有溫度的工具:由 Git 衍生出來的 GitHub/GitLab 能夠幫你很好地管理編程工做,好比GitHub包括即時通訊功能,開發者能夠互相審覈、評論和打分。同時還包括 wiki、fork、pull request、issue……集成了與編程相關的工做,讓咱們的工做能夠呈如今一個工做平臺上,並以此來規範整個團隊的工做。
- 分佈式管理:你能夠離線提交代碼,而不用擔憂網絡問題。
- 合併分支管理:合併分支後也能查看整個代碼的變動記錄
- 分支快速切換:Git 切換分支的時候一般很快,不像其餘版本管理器,好比SVN,每一個分支一份拷貝。
git經常使用命令
跳轉這裏查看經常使用命令:經常使用命令github
這裏記錄本身平時常用的一些命令,並非本文的重點。另外叨叨一下,有些人喜歡在集成的IDE下經過界面方式來進行操做,好比vs code或者eclipse都有傻瓜化的集成,這裏推薦使用命令行操做,我以爲有以下一些優點:編程
- 第1、能夠和IDE解耦,不用換一個IDE就要去了解對應界面的使用方法;
- 第2、命令行的操做很是快速,固然缺點是你須要記憶一些命令,可是經常使用的命令真心很少;
- 第3、命令行擁有界面沒有的體驗,好比一個簡單的git status你能夠查看內部更多的詳情;git stash命令,能夠把當前沒有完成的事先暫存一下,而後去忙別的事;git cherry-pick命令可讓你有選擇地合併提交。git add -p可讓你挑選改動提交。
![](http://static.javashuo.com/static/loading.gif)
git工做流介紹
市面上有如下幾種常見的工做流:服務器
- 中心式協同工做流【主幹開發】
- 功能分支協同工做流【特性分支】
- github協同工做流
- gitlab協同工做流
- gitflow協同工做流
中心式協同工做流
這種方式等於把git當作svn適用,不少同窗估計都是這麼用的。這種協同方式是全部的人都在 Master 分支上共享他們的代碼。網絡
流程
![](http://static.javashuo.com/static/loading.gif)
這裏的流程是這樣的:架構
- 從服務器上把代碼同步下來;
- 本地編碼後,再add/commit到本地倉庫
- 最後再push到origin master上
這裏的第三步有可能出錯,由於可能別人在你以前在相同地方已經提交了代碼,這時候你須要先(git pull --rebase)一下,若是發現衝突,就解決衝忽然後繼續合併(git rebase --continue)。到這裏你是否感受和svn愈來愈像,天天早上過來定時的update一下,而後再編碼,上傳代碼以前也是這樣先update一下,再作上傳操做?eclipse
焦油坑
這裏有幾個坑須要注意:分佈式
- 代碼衝突:建議天天編碼以前和代碼上傳以前不按期、頻繁的進行git pull --rebase。
- 代碼干擾:隨着開發團隊規模的擴大,可能你pull一個不可運行的代碼下來(push上去的人沒有用心檢查是否能夠編譯經過),這時候你的麻煩開始產生了,你要停下手上的活,花費可能好久的時間去把代碼編譯經過,因而咱們常常聽到不少開發人員在那邊互相抱怨,怎麼就不能好好檢查後再上傳呢,還讓不讓人寫代碼,好好學習一下svn怎麼用吧……
總結:
中心式的協同顯然沒法知足團隊規模的擴展和代碼的干擾衝突,並且產品上線後,master的BUG會直接影響生產環境,也就說master實際上是不穩定的,而用不穩定的主幹直接和生產環境掛鉤,後果可想而知。因此該流程不適用產品線迭代開發和持續更新,若是你只有1-2個開發人員那就罷了,不然通常不建議使用這種方式,接下來就要介紹如何去避免上面的這些焦油坑,也就是咱們的功能分支協同工做流上場了。svn
功能分支協同工做流
上面的那種方式有一個問題,就是你們都在一個主幹上開發程序,對於小團隊或是小項目你能夠這麼幹,可是對比較大的項目或是人比較多的團隊,這麼幹就會有不少問題。最大的問題就是代碼可能干擾太嚴重。尤爲是,咱們想安安靜靜地開發一個功能時,咱們想把各個功能的代碼變更隔離開來,同時各個功能又會有多個開發人員在開發。
這時,咱們不想讓各個功能的開發人員都在 Master 分支上共享他們的代碼。咱們想要的協同方式是這樣的:同時開發一個功能的開發人員能夠分享各自的代碼,可是不會把代碼分享給開發其餘功能的開發人員,直到整個功能開發完畢後,纔會分享給其餘的開發人員(也就是進入主幹分支),接下來就是咱們的功能分支上場了。
流程:
![](http://static.javashuo.com/static/loading.gif)
這裏的流程是這樣的:
- 切割開發分支:從git服務器上clone一份代碼下來,並在本地切割出一個分支(git checkout -b jackyfei_dev);
- 編碼提交:在分支下進行本地編碼,後進行git add和git commit;
- 合併分支:切換到master分支(git checkout master),合併jackyfei_dev分支(git merge jackyfei_dev);
- 推送到服務器:最後push到服務器(git push -u origin master),注意這裏推送後不會把分支一塊兒推送到服務器,若是要推送分支上去可使用命令:git push origin jackyfei_dev;
- 代碼重審或代碼測試[可選步驟]:代碼審查人員或代碼測試人員在你的分支上審查或測試經過後,在服務器端進行合併操做。該步驟根據團隊大小進行選擇,非必作項。
- 刪除分支[可選步驟]:這裏有點閱後即焚的感受(git branch -d jackyfei_dev),固然你不刪除也無妨,後續能夠繼續使用。
切割分支:
![](http://static.javashuo.com/static/loading.gif)
合併分支:
![](http://static.javashuo.com/static/loading.gif)
推送分支:
![](http://static.javashuo.com/static/loading.gif)
注意事項
- 刪除分支:若是你在還沒合併分支的時候,就要進行分支刪除操做,git會有一個提示不能刪除的操做,若是有重要的代碼沒有合併,建議不要-D強制刪除。
- 分支衝突:在合併的過程會出現衝突,以下圖所示,這時候須要手動解決衝突,方式和svn同樣。手動合併後,再git add/git commit就能夠了。
- 版本同步:這裏的master和線上的版本保持同步,因此master必須儘可能保證是乾淨的,穩定的,通常不要輕易去動他。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
焦油坑
這裏和注意事項不一樣,羅列的是該協做方式的缺陷:
- 線上出現BUG,本地分支正開發到一半,還沒通過測試,沒法進行發佈,這時該如何解決?
- master沒法保證必定是純淨的,由於每一個人均可以merge上去
總結:
咱們能夠看到,其實,這種開發也是以服務器爲中心的開發,還不是 Git 分佈式開發,它只不過是用分支來完成代碼改動的隔離。這裏隔離的內容不叫項目而是小功能,這符合了產品快速迭代的需求。
若是團隊規模不大,採用這種分支協同反而可能增長沒必要要的工做,因此要根據團隊規模和現實當中的問題進行選型,通常團隊超過兩我的以上,並且線上環境頻繁變動致使常常性的出現不穩定的異常,這種協同方式仍是挺不錯的。這裏要思考的是,若是線上出了問題,本地開發一半沒法進行發佈的問題該如何處理呢?
GitFlow協同工做流
針對功能分支工做流的不足,GitFlow出現了,該工做流總共有5個分支,而其中的master和developer兩個分支須要長期維護,其餘的分支都是能夠隨時「閱後即焚」的。
流程
![](http://static.javashuo.com/static/loading.gif)
這裏的流程是這樣的:
- Feature 分支:也就是功能分支,用於開發功能,其對應的是開發環境,能夠「閱後即焚」。
- Developer 分支:是開發分支,一旦功能開發完成,就向Developer 分支合併,合併完成後,刪除功能分支。這個分支對應的是集成測試環境。
- Release 分支:當 Developer 分支測試達到能夠發佈狀態時,開出一個 Release 分支來,而後作發佈前的準備工做。這個分支對應的是預發環境。之因此須要這個 Release 分支,是咱們的開發能夠繼續向前,不會由於要發佈而被 block 住而不能提交。一旦 Release 分支上的代碼達到能夠上線的狀態,那麼須要把 Release 分支向 Master 分支和 Developer 分支同時合併,以保證代碼的一致性。而後再把 Release 分支刪除掉。
- Hotfix 分支:是用於處理生產線上代碼的 Bug-fix,每一個線上代碼的 Bug-fix 都須要開一個 Hotfix 分支,完成後,向 Developer 分支和 Master 分支上合併。合併完成後,刪除 Hotfix 分支。
- Master 分支:也就是主幹分支,用做發佈環境,上面的每一次提交都是能夠發佈到線上環境的。
主要事項
- 咱們須要長期維護 Master 和 Developer 兩個分支。
- Release 和 Hotfix 分支須要同時向兩個分支做合併。因此,若是沒有一個好的工具來支撐的話,這會由於咱們可能會忘了作一些操做而致使代碼不一致。
- GitFlow 協同雖然工做流比較重。可是它幾乎能夠應對全部公司的各類開發流程,包括瀑布模型,或是快速迭代模型。
焦油坑
- 分支太多,因此會出現 git log 混亂的局面。
- 在開發得足夠快的時候,你會以爲同時維護 Master 和 Developer 兩個分支是很太無聊,由於大部分狀況下二者都是同樣的。
- 管理變得很是複雜。尤爲當你想回滾某些人的提交時,你就會發現這事彷佛有點兒很差幹了。
- 工做過程當中,你會來來回回地切換工做的分支,有時候一不當心沒有切換,就提交到了不正確的分支上,你還要回滾和從新提交等等。
GitHub Flow
流程
除非你是開源項目或者有購買github企業版,不然通常企業不會把核心代碼託管在公共的github上面。
![](http://static.javashuo.com/static/loading.gif)
- 開發人員都把github上的代碼 fork 到本身的代碼倉庫中。
- 開發容易代碼庫有兩個遠程倉庫,一個是本身fork的庫,一個是官方的庫。
- 開發人員在本地建「功能分支」,在這個分支上作代碼開發。
- 開發完成後,功能分支被 push 到開發人員本身的代碼倉庫中。
- 而後,向「官方庫」發起 pull request,並作 Code Review。
- 一旦經過,就向官方庫進行合併。
焦油坑
- GitHub Flow 這種玩法雖然變得很簡單,可是沒能把咱們的代碼和運行環境給聯繫在一塊兒。
GitLab Flow
流程
![](http://static.javashuo.com/static/loading.gif)
以上是引入環境分支流程:
- 從master分支拉取一個預發佈環境分支
- 從預發佈環境分支拉取一個生產環境分支
流程雖然簡單,可是增長分支後都是工做量,若是有很好的引入CI/CD,其實這一步也是多餘的。以上主要是針對2C的互聯網業務,2B的要看狀況來處理,實時性沒有那麼強。
![](http://static.javashuo.com/static/loading.gif)
以上是引入版本分支流程:
對於版本和代碼分支的問題,我以爲這應該是有意義的,可是,最好不要維護太多的版本,版本應該是短暫的,等新的版本發佈時,老的版本就應該刪除掉了。
總結
總之,GitFlow大而全,可是很重;中心式協同流簡單但擴展性很差;功能分支和GitHub協同流輕量靈活(無須關注環境和多版本),適應性強大(既能適應快速開發和迭代,也適應CI/CD),我的傾向使用這功能分支協同工做流。固然沒有一招鮮吃遍天的銀彈,具體選擇什麼協做流程仍是要具體分析,好比GitFlow的這種流程,能夠考慮把Release分支裁剪掉,保證輕量化的同時,也能知足實際流程的須要;中心式的流程增長版本分支,也能很好的管理產品的版本代碼。
當咱們把精力放在軟件架構和開發流程優化上,咱們的git協同流會變得更加簡單,因此與其熟練玩弄git協同流,不如放心思放在架構和開發流程的優化上,這纔有事倍功半的效果。最後附上對比圖,供你選擇和參考,若是大家的團隊有更好的用法,請多賜教。
![](http://static.javashuo.com/static/loading.gif)