隨着互聯網時代的來臨與發展,尤爲分佈式開發的大力引入,對於開發工程師來講,代碼管理變成了頭等難題。10多我的或者更多的成員的研發團隊如何管理同一份代碼,異地辦公如何跟同事有效的維護同一份代碼?下面直接介紹Git,就不對Git和其餘的版本管理工具進行比較了。css
Git屬於分佈式的版本控制系統,它具備如下特色:html
分佈式工做流程:git
同傳統的集中式版本控制系統(CVCS)不一樣,Git 的分佈式特性使得開發者間的協做變得更加靈活多樣。在集中式系統中,每一個開發者就像是鏈接在集線器上的節點,彼此的工做方式大致相像。而在 Git 中,每一個開發者同時扮演着節點和集線器的角色——也就是說,每一個開發者既能夠將本身的代碼貢獻到其餘的倉庫中,同時也能維護本身的公開倉庫,讓其餘人能夠在其基礎上工做並貢獻代碼。由此,Git 的分佈式協做能夠爲你的項目和團隊衍生出種種不一樣的工做流程,接下來的章節會介紹幾種利用了 Git 的這種靈活性的常見應用方式。咱們將討論每種方式的優勢以及可能的缺點;你能夠選擇使用其中的某一種,或者將它們的特性混合搭配使用。
Git 提供的有如下三種工做流程github
目前咱們團隊使用的是最簡單的方式,集中式工做流程,隨着研發團隊的壯大可能會選擇使用第二種,下面咱們分別介紹下三種工做流數據庫
1.集中式工做流 vim
集中式系統中一般使用的是單點協做模型——集中式工做流。一箇中心集線器,或者說倉庫,能夠接受代碼,全部人將本身的工做與之同步。若干個開發者則做爲節點——也就是中心倉庫的消費者——而且與其進行同步。服務器
這意味着若是兩個開發者從中心倉庫克隆代碼下來,同時做了一些修改,那麼只有第一個開發者能夠順利地把數據推送回共享服務器。第二個開發者在推送修改以前,必須先將第一我的的工做合併進來,這樣纔不會覆蓋第一我的的修改。這和 Subversion (或任何 CVCS)中的概念同樣,並且這個模式也能夠很好地運用到 Git 中。若是在公司或者團隊中,你已經習慣了使用這種集中式工做流程,徹底能夠繼續採用這種簡單的模式。只須要搭建好一箇中心倉庫,並給開發團隊中的每一個人推送數據的權限,就能夠開展工做了。Git 不會讓用戶覆蓋彼此的修改。例如 John 和 Jessica 同時開始工做。 John完成了他的修改並推送到服務器。接着 Jessica 嘗試提交她本身的修改,卻遭到服務器拒絕。她被告知她的修改正經過非快進式(non-fast-forward)的方式推送,只有將數據抓取下來而且合併後方能推送。這種模式的工做流程的使用很是普遍,由於大多數人對其很熟悉也很習慣。固然這並不侷限於小團隊。利用 Git 的分支模型,經過同時在多個分支上工做的方式,即便是上百人的開發團隊也能夠很好地在單個項目上協做。網絡
2.集成管理者工做流 分佈式
Git 容許多個遠程倉庫存在,使得這樣一種工做流成爲可能:每一個開發者擁有本身倉庫的寫權限和其餘全部人倉庫的讀權限。這種情形下一般會有個表明``官方''項目的權威的倉庫。要爲這個項目作貢獻,你須要從該項目克隆出一個本身的公開倉庫,而後將本身的修改推送上去。接着你能夠請求官方倉庫的維護者拉取更新合併到主項目。維護者能夠將你的倉庫做爲遠程倉庫添加進來,在本地測試你的變動,將其合併入他們的分支並推送回官方倉庫。這一流程的工做方式以下所示:ide
這是 GitHub 和 GitLab 等集線器式(hub-based)工具最經常使用的工做流程。人們能夠容易地將某個項目派生成爲本身的公開倉庫,向這個倉庫推送本身的修改,併爲每一個人所見。這麼作最主要的優勢之一是你能夠持續地工做,而主倉庫的維護者能夠隨時拉取你的修改。貢獻者沒必要等待維護者處理完提交的更新——每一方均可以按照本身節奏工做。
3.司令官與副官工做流
這實際上是多倉庫工做流程的變種。通常擁有數百位協做開發者的超大型項目纔會用到這樣的工做方式,例如著名的 Linux 內核項目。被稱爲副官(lieutenant)的各個集成管理者分別負責集成項目中的特定部分。全部這些副官頭上還有一位稱爲司令官(dictator)的總集成管理者負責統籌。司令官維護的倉庫做爲參考倉庫,爲全部協做者提供他們須要拉取的項目代碼。整個流程看起來是這樣的
這種工做流程並不經常使用,只有當項目極爲龐雜,或者須要多級別管理時,纔會體現出優點。利用這種方式,項目總負責人(即司令官)能夠把大量分散的集成工做委託給不一樣的小組負責人分別處理,而後在不一樣時刻將大塊的代碼子集統籌起來,用於以後的整合。
介紹了上面三種工做流,想必你必定有想法使用哪種了,選擇一個適合本身團隊的工做流,只要是嚴格按照這種規則執行的話,相信你的研發團隊對於代碼的管理必定不會再混亂了,這也會大大提高團隊的工做效率。
幾乎全部的版本控制系統都以某種形式支持分支。使用分支意味着你能夠把你的工做從開發主線上分離開來,以避免影響開發主線。在不少版本控制系統中,這是一個略微低效的過程——經常須要徹底建立一個源代碼目錄的副本。對於大項目來講,這樣的過程會耗費不少時間。 有人把 Git 的分支模型稱爲它的``必殺技特性'',也正由於這一特性,使得 Git 從衆多版本控制系統中脫穎而出。爲什麼 Git 的分支模型如此出衆呢? Git 處理分支的方式可謂是難以置信的輕量,建立新分支這一操做幾乎能在瞬間完成,而且在不一樣分支之間的切換操做也是同樣便捷。與許多其它版本控制系統不一樣,Git 鼓勵在工做流程中頻繁地使用分支與合併,哪怕一天以內進行許屢次。理解和精通這一特性,你便會意識到 Git 是如此的強大而又獨特,而且今後真正改變你的開發方式。
Git 建立分支
Git 是怎麼建立新分支的呢?很簡單,它只是爲你建立了一個能夠移動的新的指針。好比,建立一個 testing
分支,你須要使用git branch
命令:
$ git branch testing
這會在當前所在的提交對象上建立一個指針
那麼,Git 又是怎麼知道當前在哪個分支上呢?也很簡單,它有一個名爲HEAD
的特殊指針。請注意它和許多其它版本控制系統(如 Subversion 或 CVS)裏的HEAD
概念徹底不一樣。在 Git 中,它是一個指針,指向當前所在的本地分支。在本例中,你仍然在master
分支上。由於git branch
命令僅僅建立一個新分支,並不會自動切換到新分支中去。
你能夠簡單地使用git log
命令查看各個分支當前所指的對象。提供這一功能的參數是--decorate
。
$ git log --oneline --decoratef30ab (HEAD, master, testing) add feature #32 - ability to add new 34ac2 fixed bug #1328 - stack overflow under certain conditions 98ca9 initial commit of my project
正上,當前master
和testing
分支均指向校驗和以f30ab
開頭的提交對象。
分支切換
要切換到一個已存在的分支,你須要使用git checkout
命令。咱們如今切換到新建立的testing
分支去:
$ git checkout testing
這樣HEAD就指向testing分支了。
那麼,這樣的實現方式會給咱們帶來什麼好處呢?如今不妨再提交一次:
$ vim test.rb $ git commit -a -m 'made a change'
如上圖所示,你的testing
分支向前移動了,可是master
分支卻沒有,它仍然指向運行git checkout
時所指的對象。這就有意思了,如今咱們切換回master
分支看看:
$ git checkout master
這條命令作了兩件事。一是使 HEAD 指回master分支,二是將工做目錄恢復成master分支所指向的快照內容。也就是說,你如今作修改的話,項目將始於一個較舊的版本。本質上來說,這就是忽略testing分支所作的修改,以便於向另外一個方向進行開發。
如今咱們稍微再作些修改並commit
:
$ vim test.rb $ git commit -a -m 'made other changes'
如今,這個項目的提交歷史已經產生了分叉。由於剛纔你建立了一個新分支,並切換過去進行了一些工做,隨後又切換回 master
分支進行了另一些工做。上述兩次改動針對的是不一樣分支:你能夠在不一樣分支間不斷地來回切換和工做,並在時機成熟時將它們合併起來。而全部這些工做,你須要的命令只有branch
、checkout
和commit
。
Git 合併分支
接下來我們舉個稍微複雜點的例子,三個分支的分別處理不一樣的事情,最後合併到一塊
首先,咱們假設你正在你的項目上工做,而且已經有一些提交, 以下圖:
如今,你已經決定要解決你的公司使用的問題追蹤系統中的 #53
問題。想要新建一個分支並同時切換到那個分支上,你能夠運行一個帶有-b
參數的git checkout
命令:
$ git checkout -b iss53 Switched to a new branch "iss53"
它是下面兩條命令的簡寫:
$ git branch iss53 $ git checkout iss53
你繼續在 #53
問題上工做,而且作了一些提交。在此過程當中,iss53
分支在不斷的向前推動,由於你已經檢出到該分支(也就是說,你的HEAD
指針指向了iss53
分支)
$ vim index.html $ git commit -a -m 'added a new footer [issue 53]'
當你在iss53
這個分支上正在順暢的工做,這時候有個特別緊急的問題須要你來修復,那麼爲了避免影響iss53
的正常工做,你須要作的是從新切換到master
分支上來,在master
分支的基礎上再建立一個新的分支 hotfix
,而後在hotfix
分支解決緊急的問題。
$ git checkout -b hotfix Switched to a new branch 'hotfix' $ vim index.html $ git commit -a -m 'fixed the broken email address' [hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+)
這個時候hotfix
分支上的問題完全解決了,你須要合併到master
分支,而且部署上線, 那麼你只須要在master
分支使用git merge
命令就能夠了
$ git checkout master $ git merge hotfix Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+)
在合併的時候,你應該注意到了"快進(fast-forward
)"這個詞。因爲當前master
分支所指向的提交是你當前提交(有關 hotfix
的提交)的直接上游,因此 Git 只是簡單的將指針向前移動。換句話說,當你試圖合併兩個分支時,若是順着一個分支走下去可以到達另外一個分支,那麼 Git 在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況下的合併操做沒有須要解決的分歧——這就叫作 「快進(fast-forward
)」。如今,最新的修改已經在master分支所指向的提交快照中了。
關於這個緊急問題的解決方案發布以後,你準備回到被打斷以前時的工做中。然而,你應該先刪除hotfix
分支,由於你已經再也不須要它了, master
分支已經指向了同一個位置。你可使用帶-d
選項的git branch
命令來刪除分支:
$ git branch -d hotfix Deleted branch hotfix (3a0874c).
如今你能夠切換回你正在工做的分支繼續你的工做,也就是針對iss53
分支
$ git checkout iss53 Switched to branch "iss53" $ vim index.html $ git commit -a -m 'finished the new footer [issue 53]' [iss53 ad82d7a] finished the new footer [issue 53] 1 file changed, 1 insertion(+)
這個時候 #53
問題解決後你就能夠把代碼合併到master了,操做跟剛纔的htofix
分支處理方式同樣
$ git checkout master Switched to branch 'master' $ git merge iss53 Merge made by the 'recursive' strategy.index.html | 1 + 1 file changed, 1 insertion(+)
可是這和你以前合併hotfix分支的時候看起來有一點不同。在這種狀況下,你的開發歷史從一個更早的地方開始分叉開來(diverged
)。由於,master
分支所在提交併非iss53
分支所在提交的直接祖先,Git 不得不作一些額外的工做。出現這種狀況的時候,Git 會使用兩個分支的末端所指的快照(C4和C5)以及這兩個分支的工做祖先(C2),作一個簡單的三方合併。
和之間將分支指針向前推動所不一樣的是,Git 將這次三方合併的結果作了一個新的快照而且自動建立一個新的提交指向它。這個被稱做一次合併提交,它的特別之處在於他有不止一個父提交。
這個時候如何不須要iss53
分支的話,你也能夠刪除iss53
分支了
遠程分支
以github
爲例,目前不少開源項目以及公司的研發項目代碼通常都託管在github
,那麼就出現了遠程倉庫,遠程分支等這些概念。
下面咱們從github
遠程倉庫clone
下來一份代碼
若是你在本地的master分支作了一些工做,然而在同一時間,其餘人推送提交到git@github.com:glj1102/git_test.git
並更新了它的master分支,那麼你的提交歷史將向不一樣的方向前進。也許,只要你不與 origin 服務器鏈接,你的origin/master指針就不會移動。
若是要同步你的工做,運行git pull
命令。這個命令是抓取遠程分支數據到本地分支,而且更新本地數據庫,移動origin/master指針指向新的、更新後的位置。同時你也能夠執行 git push
命令把你本地修改的數據提交到遠程分支。
咱們使用的是 Worktile + github
來管理團隊的,平時團隊溝通,任務分配都是經過Worktile來作的,那麼 Worktile 與github如何關聯的呢?
Worktile綁定github代碼倉儲
在Worktile的後臺管理 > 服務管理
中找到github
,點擊添加
下一步會讓你選擇Worktile的一個聊天羣組
,以後github的提交記錄就會發送到這個羣組中:
添加服務以後須要進行一些配置,配置方式有兩種,一種是受權模式
,選擇倉儲,選擇事件, 另外一種是普通模式
,這種模式Worktile會生成一個Webhook
連接,拿到這個連接能夠直接在github倉儲中進行Webhook配置:
具體的配置Worktile後臺github服務設置中有教程。
Worktile接收github發送的操做記錄
根據不配置時選擇的事件不一樣,github會發送不一樣的記錄消息
經過上面對Git的介紹,對於團隊管理者來講,如何使用Git來有效的管理團隊代碼應該會有最基本的概念,那接下來就須要你真正的花時間來實踐了。那麼對於Git的命令集網上有不少例子的,下面我這裏介紹兩本Git的基本入門教程:
Git 簡易指南 http://www.bootcss.com/p/git-...
Git 圖解 http://marklodato.github.io/v...
本文做者:龔林傑
文章來源:Worktile技術博客文章轉載請註明出處。