(本文假設各位已經對基本git的基本概念、操作有一定的理解,如無相關git知識,可以參考Pro Git這本書進行相關的學習和練習)
很多項目開發都會采用git這一優秀的分布式版本管理工具進行項目版本管理,使用github開源平台作為代碼倉庫托管平台。由於git的使用非常靈活,在實踐當中衍生了很多種不同的工作流程,不同的項目、不同的團隊會有不同的協作方式。
本文將介紹一種前人已經在各種大小項目中經過千錘百煉總結出來的一種比較成功的git工作流,這種工作流已經被成功用於許多團隊開發當中。掌握git,掌握這種工作流,對大家以后的學習、開發工作大有好處。
先上一張圖嚇大家一下:
上面一張圖展示了一種使用git進行項目協同開發的模式,接下來會進行詳細介紹。
倉庫(Repository)
在項目的開始到結束,我們會有兩種倉庫。一種是源倉庫(origin),一種是開發者倉庫。上圖中的每個矩形都表示一個倉庫,正中間的是我們的源倉庫,而其他圍繞着源倉庫的則是開發者倉庫。
源倉庫
在項目的開始,項目的發起者構建起一個項目的最原始的倉庫,我們把它稱為origin
,例如我們的PingHackers網站,origin
就是這個PingHackers/blog了。源倉庫的有兩個作用:
- 匯總參與該項目的各個開發者的代碼
- 存放趨於穩定和可發布的代碼
源倉庫應該是受保護的,開發者不應該直接對其進行開發工作。只有項目管理者(通常是項目發起人)能對其進行較高權限的操作。
開發者倉庫
上面說過,任何開發者都不會對源倉庫進行直接的操作,源倉庫建立以后,每個開發者需要做的事情就是把源倉庫的“復制”一份,作為自己日常開發的倉庫。這個復制,也就是github上面的fork
。
每個開發者所fork的倉庫是完全獨立的,互不干擾,甚至與源倉庫都無關。每個開發者倉庫相當於一個源倉庫實體的影像,開發者在這個影像中進行編碼,提交到自己的倉庫中,這樣就可以輕易地實現團隊成員之間的並行開發工作。而開發工作完成以后,開發者可以向源倉庫發送pull request
,請求管理員把自己的代碼合並到源倉庫中,這樣就實現了分布式開發工作,和最后的集中式的管理。
分支(Branch)
分支是git中非常重要的一個概念,也是git這一個工具中的大殺器,必殺技。在其他集中式版本管理工具(SVN/CVS)把分支定位為高級技巧, 而在git中,分支操作則是每個開發人員日常工作流。利用git的分支,可以非常方便地進行開發和測試,如果使用git沒有讓你感到輕松和愉悅,那是因為 你還沒有學會使用分支。不把分支用出一點翔來,不要輕易跟別人說你用過git。
在文章開頭的那張圖中,每一個矩形內部紛繁的枝蔓便是git的分支模型。可以看出,每個開發者的倉庫都有自己的分支路線,而這些分支路線會通過代碼匯總映射到源倉庫中去。
我們為git定下一種分支模型,在這種模型中,分支有兩類,五種
- 永久性分支
master branch
:主分支develop branch
:開發分支
- 臨時性分支
feature branch
:功能分支release branch
:預發布分支hotfix branch
:bug修復分支
永久性分支
永久性分支是壽命無限的分支,存在於整個項目的開始、開發、迭代、終止過程中。永久性分支只有兩個master
和develop
。
master:主分支從項目一開始便存在,它用於存放經過測試,已經完全穩定代碼;在項目開發以后的任何時刻當中,master
存放的代碼應該是可作為產品供用戶使用的代碼。所以,應該隨時保持master
倉庫代碼的清潔和穩定,確保入庫之前是通過完全測試和代碼reivew的。master
分支是所有分支中最不活躍的,大概每個月或每兩個月更新一次,每一次master
更新的時候都應該用git打上tag
,說明你的產品有新版本發布了。
develop:開發分支,一開始從master分支中分離出來,用於開發者存放基本穩定代碼。之前說過,每個開發者的倉庫相當於源倉庫的一個鏡像,每個開發者自己的倉庫上也有master
和develop
。開發者把功能做好以后,是存放到自己的develop
中,當測試完以后,可以向管理者發起一個pull request
,請求把自己倉庫的develop
分支合並到源倉庫的develop
中。
所有開發者開發好的功能會在源倉庫的develop
分支中進行匯總,當develop
中的代碼經過不斷的測試,已經逐漸趨於穩定了,接近產品目標了。這時候,我們就可以把develop
分支合並到master
分支中,發布一個新版本。所以,一個產品不斷完善和發布過程就正如下圖:
注意,任何人不應該向master
直接進行無意義的合並、提交操作。正常情況下,master
只應該接受develop
的合並,也就是說,master
所有代碼更新應該源於合並develop
的代碼。
暫時性分支
暫時性分支和永久性分支不同,暫時性分支在開發過程中是一定會被刪除的。所有暫時性分支,一般源於develop
,最終也一定會回歸合並到develop
。
feature:功能性分支,是用於開發項目的功能的分支,是開發者主要戰斗陣地。開發者在本地倉庫從develop
分支分出功能分支,在該分支上進行功能的開發,開發完成以后再合並到develop
分支上,這時候功能性分支已經完成任務,可以刪除。功能性分支的命名一般為feature-*
,*為需要開發的功能的名稱。
舉一個例子,假設我是一名PingHackers網站的開發者,已經把源倉庫fork了,並且clone到了本地。現在要開發PingHackers網站的“討論”功能。我在本地倉庫中可以這樣做:
step 1: 切換到develop
分支
>>> git checkout develop
step 2: 分出一個功能性分支
>>> git checkout -b feature-discuss
step 3: 在功能性分支上進行開發工作,多次commit,測試以后...
step 4: 把做好的功能合並到develop
中
>>> git checkout develop # 回到develop分支 >>> git merge --no-ff feature-discuss # 把做好的功能合並到develop中 >>> git branch -d feature-discuss # 刪除功能性分支 >>> git push origin develop # 把develop提交到自己的遠程倉庫中
這樣,就完成一次功能的開發和提交。
release:預發布分支,當產品即將發布的時候,要進行最后的調整和測試,這時候就可以分出一個預發布分支,進行最后的bug fix。測試完全以后,發布新版本,就可以把預發布分支刪除。預發布分支一般命名為release-*
。
hotfix:修復bug分支,當產品已經發布了,突然出現了重大的bug。這時候就要新建一個hotfix
分支,繼續緊急的bug修復工作,當bug修復完以后,把該分支合並到master
和develop
以后,就可以把該分支刪除。修復bug分支命名一般為hotfix-*
release
和hotfix
分支離我們還比較遙遠。。就不詳述,有興趣的同學可以參考本文最后的參考資料進行學習。
工作流(Workflow)
啰嗦講了這么多,概念永遠是抽象的。對於新手來說,都喜歡一步一步的步驟傻瓜教程,接下來,我們就一步一步來操作上面所說的工作流程,大家感受一下:
Step 1:源倉庫的構建
這一步通常由項目發起人來操作,我們這里把管理員設為PingHackers,假設PingHackers已經為我們建立起了一個源倉庫PingHackers/git-demo,並且已經初始化了兩個永久性分支master
和develop
,如圖:
Step 2:開發者fork源倉庫
源倉庫建立以后,每個開發就可以去復制一份源倉庫到自己的github賬號中,然后作為自己開發所用的倉庫。假設我是一個項目中的開發者,我就到PingHackers/git-demo項目主頁上去fork
:
fork
完以后,我就可以在我自己的倉庫列表中看到一個和源倉庫一模一樣的復制品。這時就應該感嘆,你以后要和它相依為命了:
Step 3:把自己開發者倉庫clone到本地
這一步應該不用教,git clone
Step 4:構建功能分支進行開發
進入倉庫中,按照前面說所的構建功能分支的步驟,構建功能分支進行開發、合並,假設我現在要開發一個“討論”功能:
>>> git checkout develop # 切換到`develop`分支 >>> git checkout -b feature-discuss # 分出一個功能性分支 >> touch discuss.js # 假裝discuss.js就是我們要開發的功能 >> git add . >> git commit -m 'finish discuss feature' # 提交更改 >>> git checkout develop # 回到develop分支 >>> git merge --no-ff feature-discuss # 把做好的功能合並到develop中 >>> git branch -d feature-discuss # 刪除功能性分支 >>> git push origin develop # 把develop提交到自己的遠程倉庫中
這時候,你上自己github的項目主頁中develop
分支中看看,已經有discuss.js
這個文件了:
Step 5:向管理員提交pull request
假設我完成了“討論”功能(當然,你還可能對自己的develop
進行了多次合並,完成了多個功能),經過測試以后,覺得沒問題,就可以請求管理員把自己倉庫的develop分支合並到源倉庫的develop分支中,這就是傳說中的pull request
。
點擊上圖的綠色按鈕,開發者就可以就可以靜靜地等待管理員對你的提交的評審了。
Step 6 管理員測試、合並
接下來就是管理員的操作了,作為管理員的PingHackers登陸github,便看到了我對源倉庫發起的pull request
。
這時候PingHackers需要做的事情就是:
- 對我的代碼進行review。github提供非常強大的代碼review功能:
-
在他的本地測試新建一個測試分支,測試我的代碼:
>> git checkout develop # 進入他本地的develop分支 >> git checkout -b livoras-develop # 從develop分支中分出一個叫livoras-develop的測試分支測試我的代碼 >> git pull https://github.com/livoras/git-demo.git develop # 把我的代碼pull到測試分支中,進行測試
-
判斷是否同意合並到源倉庫的
develop
中,如果經過測試沒問題,可以把我的代碼合並到源倉庫的develop
中:>> git checkout develop >> git merge --no-ff livoras-develop >> git push origin develop
注意,PingHakers一直在操作的倉庫是源倉庫。所以我們經過上面一系列操作以后,就可以在源倉庫主頁中看到:
經過輾轉曲折的路程,我們的discuss.js
終於從我的開發倉庫的功能分支到達了源倉庫的develop
分支中。以上,就是一個git & github協同工作流的基本步驟。
總結
git這一個工具博大精深,很難想象竟然有使用如此惡心而又如此靈活和優雅的工具存在;此又為一神器,大家還是多動手,多查資料,讓git成為自己 的一項基本技能,幫助自己處理各種項目團隊協同工作的問題,成為一個高效的開發者、優秀的項目的管理者。送大家一張神圖,好好領悟:
最后給出一些參考資料,供參考學習。
轉載:http://www.kuqin.com/shuoit/20141213/343854.html