好代碼是管出來的——Git的分支工做流與Pull Request

   上一篇文章介紹了經常使用的版本控制工具以及git的基本用法,從基本用法來看git與其它的版本控制工具好像區別不大,都是對代碼新增、提交進行管理,能夠查看提交歷史、代碼差別等功能。但實際上git有一個重量級的功能「分支」,git的分支與其它工具的分支不一樣,git分支的操做徹底在本地進行,因此能夠快速的建立和切換。html

  版本控制工具除了對代碼進行管理外,實際上它還影響了整個軟件編碼的工做流程,git由於其分支特性使得開發流程發生了變化,本文將從如下幾點來介紹分支和git的工做流程:git

版本控制管理分支簡介

  在使用集中式的版本管理工具時,通常會在項目的倉庫中建立Trunk(主幹)、Branches(分支)、Tag(標記)幾個目錄,分別用於放置開發代碼、代碼分支以及代碼里程碑,分支的目的是爲了開發一些測試性功能或者修復Bug時從開發主線上分開避免互相影響,可是要注意的是集中式的工具建立分支的過程是由服務器完成的,當服務器完成分支的建立後,使用者還須要將分支代碼checkout到本地,若是項目較大或者網絡較慢,那麼checkout將是一個漫長的過程,因此使用集中式工具時分支的建立是相對謹慎的。
  對於Git來講分支就是整個倉庫的基礎(注:當使用git init命令建立一個倉庫時,默認會建立一個名爲master的分支),因爲Git的本地處理特性,分支的建立基本是一瞬間完成的,正由於這一特性,使用git來進行代碼開發的工做流程就有了巨大的變化,如開發功能時建立對應的分支、修復bug(不只僅是生產bug,任何測試產生的bug均可以建立分支)以及開源項目任何人均可以建立本身的分支進行開發。程序員

Git的分支

分支的基本操做

  • 查看分支:(git branch)

  

  • 分支的建立:(git branch TranslateMainPage)

  

  • 分支的切換:(git checkout TranslateMainPage)

  

  注:git checkout -b TranslateMainPage至關於執行了建立和切換兩個命令。github

  • 分支的合併:(git merge TranslateMainPage)

  

  • 分支的刪除:(git branch -d TranslateMainPage)

  

  • 將本地分支上傳到遠程服務器:(git push -u origin version0  注:-u是--set-upstream的縮寫)

  

  

遠程分支以其基本操做

  Git的操做都是基於分支的,同時Git做爲一個分佈式的版本控制工具可使用遠程託管平臺來進行代碼庫託管,那Git的分支是如何在遠程平臺上體現的呢?
  Git中有一個remote命令,它能夠用來管理一系列被跟蹤或者說被關聯的遠程倉庫(注:remote管理的是倉庫),以下圖經過git remote以及 git remote show origin來查看遠程倉庫的信息:服務器

   

  這裏要注意的是「origin」,它其實是遠程倉庫的一個名稱,經過容易記憶名稱來代替倉庫的URL地址更加容易使用,另外若是使用git clone命令來克隆一個遠程倉庫,那麼遠程倉庫名稱會默認爲origin。
  對於遠程分支經常使用的操做有:網絡

  • 添加新的遠程倉庫:(git remote add Myblog https://github.com/yqszt/Myblog.git,Myblog是本地用來代替後面Url的名稱)

  

  • 克隆一個遠程倉庫:(git clone https://github.com/yqszt/MyBlog.git)

  

  默認建立一個名稱爲origin的遠程倉庫:app

  

  • 將數據(commit)提交到遠程倉庫:(git push origin)

  

  • 從遠程倉庫拉取更新:(git fetch)

  注:使用git fetch後,並不會將新的內容更新到工做區域的文件中,因此能夠經過git diff master origin/master命令來比較差別分佈式

  

  同時也可使用git merge命令來將更新合併到工做區域:工具

  

  注:git pull命令至關於執行了git fetch和git merge兩個命令。post

Git基於分支的工做流程

  以前提到過集中式版本工具中分支的做用是開發一些測試性功能或者修復一些穩定版本的Bug,使用分支能夠與開發主線隔離,當完成後再合併到主線中,這種開發流程被稱爲「集中式工做流」,它的工做流程可當作:

   

  1. 以主分支Trunk爲核心進行開發,換句話就是開發人員把開發代碼都提交到Trunk上,提交以前獲取全部代碼,而且保證代碼能編譯成功。
  2. 若是有測試性功能,爲了與主幹代碼分離,經過開啓分支的形式完成功能開發。(注:這裏寫測試性功能的緣由是,集中式的版本控制工具開啓分支代價相對較大,因此在建立分支的時候是謹慎的)。
  3. 當開發達到一個里程碑時,經過建立Tag分支來保存里程碑狀態,同時Tag出現問題時,能夠經過建立Bug修復分支或者直接在Tag分支上修復問題,最終將修復代碼合併到Trunk上。
  對於分佈式的Git來講,因爲它建立和切換分支的代價很小,因此能夠頻繁的建立和切換分支,而分支的功能就是與主幹代碼隔離,以致於在開發過程當中不會由於不完善的功能代碼致使主幹代碼被污染,從而致使沒法編譯經過,它主要有如下幾種開發工做流:

集中式工做流

  集中式工做流就是上面提到集中式版本控制工具中經常使用的開發流程,以主分支爲核心,全部開發人員經過更新主分支代碼完成代碼的開發工做,同時也會建立一些分支和標籤(Git的默認分支是Master):

  

功能開發工做流

  功能開發工做流程是以功能爲單位進行分支建立,其過程以下:

  

  經過建立對應的功能或問題修復分支,完成功能的開發和Bug的修復。這樣的好處就是功能與功能之間的代碼是隔離的互不影響,利用Git的快速切換分支特性,能夠在同一工做目錄下同時開發多個功能,且各個功能之間的代碼不會互相影響。另外全部新代碼均經過合併的方式合併到Master分支,這樣代碼更容易控制管理。

Gitflow工做流

  Gitflow能夠看做是功能開發工做流的完善版本,它除了Master分支、特性分支、Bug修復分支外,還引入了release、develop兩個分支來管理髮布和開發,而Master只保存穩定版本的代碼。

  

  (圖片來自http://www.javashuo.com/article/p-fbiyftjh-cc.html
  總的來講Git就是使用它快速建立和切換分支的特性,在開發過程當中經過分支來完成功能的開發、Bug修復以及代碼發佈。
  更多信息可參考:http://nvie.com/posts/a-successful-git-branching-model/
          https://blog.csdn.net/wwj_748/article/details/55226044

Git的分佈式工做流

  前面介紹了Git的特性之一「分支」的工做流,那麼Git的特性之二「分佈式」又會對開發模式帶來什麼樣的變化?

再談集中式工做流

  爲何又是集中式工做流?文章前面介紹的集中式工做流主要偏重於「分支」,全部工做的內容提交到一個Trunk或者Master的分支上。
  而這裏的集中式工做流是針對與代碼倉庫來講的,全部開發人員使用同一個代碼倉庫進行協同工做,Git中使用集中式工做流時還能夠採用特性分支或者Git Flow工做流來體現Git分支帶來的便利(注:若是一個項目的貢獻者只有一我的的話,實際上集中式工做流聯合特性或Git flow來進行開發是最適合的):

  

  在使用集中式版本控制工具時,使用的就是集中式工做流,全部的開發人員共享一個代碼倉庫,當其中一人提交代碼時須要先更新其它人的提交,可能會出現代碼衝突須要合併,還有可能會將其它人的提交覆蓋掉,同時因爲沒法保證代碼質量,甚至會出現引入了其它開發人員的代碼致使編譯不經過、測試不經過等等問題,因此在使用集中式工做流程的時候最不能缺乏的就是「溝通」。
  對於開源項目來講開發人員來自全世界,其溝通成本遠遠大於本地團隊,那麼做爲開源項目使用最普遍的版本控制工具,它是如何解決協同開發問題?

集成管理者工做流

  Git中能夠建立多個倉庫,集成管理者工做流的核心就是項目的主倉庫由「集成者」負責,其它開發人員擁有本身的倉庫,開發者把完成的工做提交到本身的公開庫中,而後「集成者」從這些公開庫中拉取代碼最終合併到主倉庫中,以下圖:

  

  這樣作有如下幾個好處:

  • 開發人員有本身的代碼庫,減小了更新、合併等操做(注:更新、合併的根源在於不一樣開發任務之間的依賴,若是依賴嚴重,那麼更新、合併是不可避免的,最理想的狀況是沒有依賴,那麼開發人員只需完成本身的工做提交便可)。
  • 全部代碼合併由「集成者」完成合並,而通常「集成者」由經驗豐富的程序員擔任,代碼合併的過程強制進行了代碼複審,對於代碼的質量是可控的,有效保證主項目代碼的乾淨整潔。
  • 因爲代碼的複審,開發人員在提交代碼時也不會太隨意,變相提升了代碼質量。

  可是相對於集中式的工做流來講因爲須要等待合併,提交工做也比較複雜,因此開發效率會相對下降。

司令官與副官工做流

  司令官與副官工做流是集成管理者工做流的拓展,引入了多級「集成者」來完成多級的代碼合併操做,該模式適用於複雜的多級管理的項目開發:

  

  

  更多關於Git分佈式工做流的內容可參考:https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows

Pull Request

  在Git中不管是集中式工做流仍是集成管理者工做流,它都有一個核心的操做就是合併代碼,對於集中式工做流來講,當分支完成開發後,須要將代碼進行合併,通常是將分支代碼合併到遠程的如Master或Develop之類的長期分支上,其流程以下:
  1. 建立一個功能分支feature1(git checkout -b feature1)。
  2. 在分支上完成功能並提交(git add & git commit)。
  3. 切換到master分支執行合併操做,並將更新推到遠程倉庫(git checkout master, git merge feature1, git push)。
  4. 刪除特性分支(git branch -d feature1)。

  過程以下圖所示:

  

  可是對於集成管理者工做流來講,集成管理者要如何知道有代碼須要合併?要如何合併代碼?Git中引入了pull request這一功能完全的改變了代碼的合併方式,這一特性也讓其成爲開源專用的版本控制工具。
  pull request是什麼?用中文翻譯過來是「拉請求」,假設如下場景:
  1. Selim開發了一個應用程序My Blog,並經過某一Git遠程託管平臺對代碼進行了託管。
  2. 7m魚複製了Selim託管的庫,而後在App上添加了一個新功能feature1。
  3. 如今7m魚想要將新功能合併到Selim的分支上應該如何操做?以下圖所示:

   

  首先能夠想到的就是使用上面提到的方法切換到Selim的master分支,而後執行git merge Feature1命令,可是若是7m魚沒有Selim/Master的修改權限呢?Selim/Master是屬於Selim的,7m魚沒法修改(典型的集成管理者模式,這裏「Selim」就是集成管理者),爲了解決這個問題Git實現了「Pull Request(拉請求)」,注意是「拉(pull)」不是「推(push)」,這個請求的目的是讓倉庫全部者來「拉」取變化,由全部者來決定合併仍是拒絕,全部者能夠根據功能是否合理、代碼是否正確、易讀等信息進行判斷,這實際上就是CodeRview的過程。
  下面建立一個新的代碼倉庫來演示Git的Pull Request,Pull Request的要求就是須要兩個遠程分支(倉庫)進行合併(代碼擁有者的分支和代碼貢獻者的分支):
  1. 克隆My Blog代碼,建立一個新的遠程倉庫(本例使用GitHub做爲託管平臺,能夠直接fork):
  git clone https://github.com/yqszt/MyBlog.git
  git remote add other https://github.com/SelimTeam/MyBlog.git
  git push -u other
  新建的遠程倉庫:

  

  2. 在克隆的代碼中修改內容並提交:

  

  3. 要將這兩次提交生成「pull request」:
  使用git request-pull命令生成拉請求信息:
  git request-pull -p 5bf2e35 https://github.com/SelimTeam/MyBlog.git master

  

  其中p表明輸出詳細內容(代碼的差別),5bf2e35對應的是提交的hash,表明更新的內容是從哪個提交開始,url表明的是貢獻者的倉庫地址,最後的master表明更新內容結束的提交,默認是分支的最新提交
  4. 將pull request信息告知做者,做者將會知道貢獻者的倉庫地址分支從哪個提交開始哪個提交結束,而且帶有詳細的變動信息
  注:這裏的告知是經過郵件等方式將上面request-pull命令生成的信息發送給做者,github等平臺上提供的pull request功能是由平臺本身實現的通知方式,關於github上的pull request後續介紹。
  5. 做者添加貢獻者的遠程倉庫,獲取並將更新合併到主分支:
  git remote add selimteam https://github.com/SelimTeam/MyBlog.git
  git fetch selimteam master
  git diff master selimteam/master

  

  git merge selimteam/master

  

  git push
  以上就完成了一次經過pull request像做者貢獻代碼的流程。

Git經常使用的GUI工具

  從上一篇文章開始都是介紹如何經過命令行的方式使用Git進行代碼管理,但在前面的文章中就提到過Git除了原生的命令模式還有GUI模式,GUI主要是針對Git的命令進行封裝而後提供了一些更便利的功能來簡化使用、提升開發效率。
  Git中經常使用的GUI工具備如下幾種:

  • SourceTree:一個開源的Git GUI工具,有一個重要的點是它提供了對git flow的支持

  

  https://www.sourcetreeapp.com/
  安裝參考:http://www.javashuo.com/article/p-kiezokne-br.html

  • GitHub For Desktop:GitHub的GUI客戶端,能夠經過它直接提交pull request(GitHub的PullRequest)

  

  • Visual Studio:VS在團隊資源管理器中集成了Git的支持,能夠在修改完成代碼後便捷的進行代碼的提交、push等操做

  

  Git的GUI工具備不少,能夠經過該連接查找:https://git-scm.com/download/gui/win

小結

  本文主要介紹了Git分支和Git的工做流,Git的工做流分爲兩個方面「分支工做流」和「分佈式工做流」,兩種工做流是混合在一塊兒使用的,前者是用分支對代碼進行隔離,後者使用多個遠程庫以及Pull Request解決了分佈式開發、合併的問題。
  文章的最後介紹了經常使用的Git GUI工具,在實際開發中選擇適合的GUI工具能夠大大的提升開發效率。

參考:
  https://git-scm.com/docs/git-request-pull
  http://www.javashuo.com/article/p-azvbhgty-ee.html
  https://longair.net/blog/2009/04/16/git-fetch-and-merge/
  http://nvie.com/posts/a-successful-git-branching-model/
  http://www.javashuo.com/article/p-fbiyftjh-cc.html
  https://blog.csdn.net/wwj_748/article/details/55226044
  https://stackoverflow.com/questions/4037928/can-you-issue-pull-requests-from-the-command-line-on-github

本文連接:http://www.javashuo.com/article/p-tksnzswt-es.html 

好代碼是管出來的——淺談.Net Core的代碼管理方法與落地(更新中...)

相關文章
相關標籤/搜索