GitHub可以通過多種途徑為版本庫授權(quán),讓版本庫成為多人共享的版本庫,從而讓項目管理者圍繞項目創(chuàng)建一個核心開發(fā)團隊。
傳統(tǒng)的集中式版本控制系統(tǒng),如CVS、SVN,所有用戶都訪問同一個版本庫。采用集中式工作模式的GitHub用戶也同樣是訪問同一版本庫。
對于由用戶gotgithub創(chuàng)建的helloworld版本庫,添加了合作者supergirl和incredible,三個人克隆版本庫使用如下命令。
- 用戶 gotgithub 克隆版本庫。
gotgithub$ git clone https://gotgithub@github.com/gotgithub/helloworld.git
- 用戶 supergirl 克隆版本庫。
supergirl$ git clone https://supergirl@github.com/gotgithub/helloworld.git
- 用戶 incredible 克隆版本庫。
incredible$ git clone https://incredible@github.com/gotgithub/helloworld.git
對于像Git這樣的分布式版本控制系統(tǒng),提交總是會成功,這是因為提交并不涉及和共享服務(wù)器的交互,是針對本地克隆版本庫進行的本地操作。采用集中式的工作模式,共享版本庫作為各個用戶各自本地版本庫數(shù)據(jù)交換、溝通的中介,只有在本地克隆版本庫需要和共享版本庫同步的時候才要和服務(wù)器建立連接。實際上無論采用分布式還是集中式的工作模式,Git都好像工作在一個獨立的分支上(克隆即分支),即使共享版本庫和本地克隆版本庫的分支名都叫做master。
三個用戶克隆gitgithub/helloworld版本庫后,各自在本地執(zhí)行了一次或多次提交。三個用戶各自的提交都會非常順利,但是一旦決定將本地提交推送到共享服務(wù)器時就可能遇到麻煩。用戶 gotgithub 先執(zhí)行推送,會非常順利。而其他人就沒有這么幸運了,會報告錯誤:遇到非快進式推送(non-fast-forward)。Git的推送操作就像SVN等集中式版本控制系統(tǒng)的提交操作那樣,先執(zhí)行者成功,后執(zhí)行者糟糕(要解決沖突,自動或手動)。
合并后推送
GitHub并不對強制推送進行限制,但是用戶不要用git push -f命令強制推送,因為那樣會覆蓋掉共享版本庫中用戶gotgithub的推送,正確的做法是獲取共享版本庫中新提交,并在本地版本庫中和本地提交合并。即執(zhí)行:
supergirl$ git fetch
supergirl$ git merge
實際上用戶supergirl只需執(zhí)行一條命令便可完成所有的操作:
supergirl$ git pull
即:git pull = git fetch + git merge。
但是合并操作并不總是會成功,如果自動合并失敗,會在暫存區(qū)對合并前后文件進行標(biāo)識,工作區(qū)進入沖突解決狀態(tài),在沖突解決完成之前不能提交。Git支持多種圖形工具幫助完成沖突解決,執(zhí)行如下命令,即可自動調(diào)用已安裝的沖突解決工具。
supergirl$ git mergetool
沖突解決完畢,執(zhí)行提交即完成沖突解決。如果在沖突解決過程把本地文件搞得一團糟,隨時可以取消合并操作。執(zhí)行命令git reset --hard會取消沖突的合并讓本地版本庫回到合并之前的狀態(tài)。
成功完成合并后將本地版本庫中的提交推送到共享版本庫:
supergirl$ git push
合并還是變基
合并并非多個開發(fā)者的工作成果融合的唯一選擇,有時甚至并非最佳選擇。一方面合并會產(chǎn)生除了合并雙方(或多方)所有提交外的一個新提交,增加了代碼審核的負擔(dān),另一方面本地多個提交混雜一起與遠程分支合并會更困難。在特定情況下,變基是合并之外的另一個選擇。

圖中右上是合并操作后的結(jié)果,右下是變基操作后的結(jié)果。
若用戶 incredible 選擇變基操作,執(zhí)行命令如下:
- 獲取遠程版本庫的提交到本地的遠程分支。
incredible$ git fetch origin
- 執(zhí)行變基操作,將本地master分支的提交變基到新的遠程分支中。
incredible$ git rebase origin/master
如果一切順利,變基后推送到共享版本庫。
incredible$ git push