Git 工做流

中心化的工做流

優點

  • 首先它讓每一個開發者都有本身的本地的完整項目副本。隔離的環境使得每一個開發都的工做獨立於項目的其它修改 —— 他們能夠在本身的本地倉庫中添加提交,徹底無視上游的開發,直到須要的時候。
  • 其次,它讓你接觸到了 Git 分支和合並模型。Git 分支被設計爲故障安全的機制,用來在倉庫之間整合代碼和共享更改。

如何工做

  • 中心化的工做將中央倉庫做爲項目中全部修改的惟一入口。默認的開發分支叫作 master,全部的更改都被提交到這個分支。這種工做流不須要 master 以外的其它分支。
  • 開發者將中央倉庫克隆到本地後開始工做。在他們的本地項目副本中,他們能夠像 SVN 同樣修改文件和提交更改;不過這些新的提交被保存在本地 —— 它們和中央倉庫徹底隔離。這使得開發者能夠將和上游的同步推遲到他們方便的時候。
  • 爲了向官方項目發佈修改,開發者將他們本地 master 分支「推送」到中央倉庫。這一步等同於 svn commit,除了 Git 添加的是全部不在中央 master 分支上的提交。

管理衝突

  • 中央倉庫代碼官方項目,所以它的提交歷史應該被視爲不可更改的。若是開發者的本地提交和中央倉庫分叉了,Git 會拒絕將它們的修改推送上去,由於這會覆蓋官方提交。

  • 在開發在提交功能以前,須要 fetch 更新中央提交,在它們之上 rebase 本身的更改。
  • 若是本地修改和上游提交的衝突時,Git 會暫停 rebase 流程,給你機會手工解決這些衝突。Git 很讚的一點是,它將 git status 和 git add 命令同時用來生成提交和解決合併衝突。這使得開發可以垂手可得的管理他們的合併。另外,若是他們改錯了什麼,Git 能讓他們輕易的退出 rebase 過程,而後重試。

例子

  • 項目管理員生成一個空的版本庫git

    ssh user@host git init --bare /path/to/repo.git
  • 三我的 A, B, C 同時編寫同一個項目,須要先在本地建立一個完整的項目副本。shell

    git clone ssh://user@host/path/to/repo.git

此時,Git 自動添加了一個名爲 origin 的運程鏈接,指向中央倉庫,以方便提交。
A 可使用標準 Git 提交流程開發功能:編輯、緩存、提交。segmentfault

git status
git add <some file>
git commit

同時,B 也在本地進行本身的開發工做。緩存

  • A 發佈了他們修改安全

    git push origin master

此時中央倉庫會將 master -> origin/master服務器

  • B 試圖發佈修改框架

    git push origin master

可是由於 A 已經提交了功能到中央倉庫,致使 B 的本地歷史和中央倉庫分叉,Git 會拒絕本次提交。ssh

  • B 若是想提交,必需要先 rebase 本地倉庫

可使用 git pull 來拉取並修改,svn

git pull --rebase origin master
  • --rebase 命令告訴 Git,在同步中央倉庫的修改以後,將 B 的全部提交移到 master 分支的頂端。

  • 若是沒有衝突的文件,B 就能夠直接進行提交了,可是若是存在衝突,能夠根據提示查找衝突的文件,修改以後,能夠繼續 rebase 操做。測試

    git add <some-file>
    git rebase --continue

一樣的,若是此時不知道本身作了什麼,能夠回滾一次操做。

git rebase --abort
  • 而後再進行 push 就能夠提交到中央版本庫了。

基於功能人分支的工做流

Feature 分支工做流

  • 掌握了中心化工做流的使用姿式,在你的開發流程中添加功能分支是一個簡單的方式,來促進協做和開發者之間的交流。這種封裝使得多個開發專一本身的功能,而不會打擾主代碼庫。它還能保證 master 分支永遠不會包含損壞的代碼,給持續集成環境帶來了很大的好處。
  • 封裝功能的開發使得 pull request 的使用成爲可能,用來啓動圍繞一個分支的討論。它給了其餘開發者在功能併入主項目以前參與決策的機會。或者,若是你開發功能時卡在一半,能夠發起一個 pull request,向同事尋求建議。重點是:pull request 使得團隊在評論其餘人的工做時,變得很是簡單。

如何工做

  • Feature 分支工做流一樣使用中央倉庫,master 一樣代碼官方的項目歷史。可是與其直接提交在本地的 master 分支,開發者每次進行新的工做時建立一個新的分支。Feature 分支應該包含描述性的名稱,好比 animated-menu-items(菜單項動畫)或 issue-*1061。每一個分支都應該有一個清晰、高度集中的目的。
  • Git 在技術上沒法區別 master 和功能分支,因此開發者能夠在 feature 分支上編輯、緩存、提交,就和中心化工做流中同樣。
  • 此外,feature 分支能夠被推送到中央倉庫。這使得你和其餘開發者共享這個功能,而又不改變官方代碼。既然 master 只是一個「特殊」的分支,在中央倉庫中儲存多個 feature 分支不會引出什麼問題。固然,這也是備份每一個開發者本地提交的好辦法。

Pull Request

  • 除了隔離功能開發以外,分支使得經過 pull request 討論修改爲爲可能。一旦有人完成了一個功能,他們不會當即將它併入 master。他們將 feature 分支推送到中央服務器上,發佈一個 pull request,請求將他們的修改併入 master。這給了其餘開發者在修改併入主代碼庫以前審查的機會。
  • 代碼審查是 pull request 的主要好處,但他們事實上被設計成爲討論代碼的通常場所。你能夠把 pull request 看做是專一某個分支的討論版。也就是說他們能夠用於開發流程以前。好比,一個開發者在某個功能上須要幫助,他只須要發起一個 pull request。感興趣的小夥伴會自動收到通知,看到相關提交中的問題。
  • 一旦 pull request 被接受了,發佈功能的行爲和中心化的工做流是同樣的。首先,肯定你本地的 master 和上游的 master 已經同步。而後,將 feature 分支併入 master 已經同步。而後能夠將 feature 分支併入 master,將更新的 master 推送回中央倉庫。

Gitflow 工做流

  • GitFlow 工做流圍繞項目發佈定義了一個嚴格的分支模型。有些地方比功能分支工做流更復雜,爲管理大型項目提供了框架。
  • 和功能分支工做流相比,這種工做流沒有增長任何新的概念或命令。它給不一樣的分支指定了特定的角色,定義它們應該如何、何時交流。除了功能分支以外,它還爲準備發佈、維護髮布、記錄發佈分別使用了單獨的分支。固然,還能享受到功能分支工做流帶來的全部好處:pull request、隔離實驗和更高效的協做。

如何工做

  • GitFlow 工做流仍然使用中央倉庫做爲開發者溝通的中心。和其它工做流同樣,開發者在本地工做,將分支推送到中央倉庫。惟一的區別在於項目的分支結構。

歷史分支

  • 和單獨的 master 分支不一樣,這種工做流使用兩個分支來記錄項目歷史。master 分支儲存官方發佈歷史,develop 分支用來整合功能分支。同時,這還方便了在 master 分支上給全部提交打上版本號標籤。

  • 工做流剩下的部分圍繞這兩個分支的差異展開。

功能分支

  • 每一個新功能都放置在本身的分支中,能夠在備份/協做時推送到中央倉庫。可是與其合併到 master,功能分支將開發分支做爲父分支。當一個功能完成時,它將被合併回 develop。功能永遠不該該支持在 master 上交互。

  • 功能分支加上 develop 分支就是咱們以前聽說的功能分支工做流。

發佈分支

  • 一旦 develop 分支的新功能足夠發佈,你能夠從 develop 分支 fork 一個發佈分支。這個分支的建立開始了下個發佈週期,只有和發佈相關的任務應該在這個分支進行,如修復 bug、生成文檔等。一旦準備好發佈,發佈分支將合併進 master,打上版本號的標籤。另外,它也應該合併回 develop,後者可能在發佈啓動以後有了新的進展。
  • 使用一個專門的分支來準備發佈確保一個團隊完善當前的發佈,其它團隊能夠繼續開發下一個發佈的功能。它還創建了清晰的開發階段。
  • 一般約定:

    • 從 develop 建立分支
    • 合併進 master 分支
    • 命名規範 release-* 或者 release/*

維護分支

  • 維護或者「緊急修復」分支用來快速給產品發佈打上補丁。這是惟一能夠從 master 上 fork 的分支。一旦修復完成了,它應該被併入 master 和 develop 分支,master 應該打上更新的版本號的標籤。
  • 有一個專門的 bug 修復開發線使得團隊可以處理 issue,而不打斷其它工做流或是要等到下一個發佈週期。你能夠將維護分支看做在 master 分支上工做的臨時發佈分支。

例子

建立一個開發分支

  • 爲默認的 master 分支建立一個互補的 develop 分支。最簡單的辦法是在本地建立一個空的 develop 分支,將他推送到服務器上:

    git branch develop
    git push -u origin develop
  • 這個分支將會包含項目中全部的歷史,而 master 將包含不徹底的版本。其餘開發者應該將中央倉庫克隆到本地,建立一個分支來追蹤 develop 分支:

    git clone http://xxx/xx/repo.git
    git checkout -b develop origin/develop

開始了新的功能

  • 當兩我的都須要在不一樣分支上開始工做,即爲本身的功能建立單獨的分支。且他們的分支都是基於 develop 而不是 master:

    git checkout -b some-feature develop
  • 他們都使用「編輯、緩存、提交」的通常約定來向功能分支添加提交:

    git status
    git add <some-file>
    git commit

完成功能

  • 添加了一些提交後,可使用 pull request,如今正是發起的好時機,請求將新功能併入 develop 分支。不然能夠先併入本地的 develop 分支,推送到中央倉庫:

    git pull origin develop
    git checkout develop
    git merge some-feature
    git push
    git branch -d some-feature
  • 第一個命令在嘗試併入功能分支以前確保 develop 分支已是最新的。注意,功能毫不該直接併入 master。衝突的處理方式和中心化工做流相同。

發佈新功能

  • 當另外的開發人員,仍在他本身的分支上工做時,開始準備項目的第一個官方發佈。和開發功能同樣,新建一個分支來封裝發佈的準備工做。這也正是發佈的版本號建立的第一步:

    git checkout -b release-0.1 develop
  • 這個分支用來整理提交,充分測試,更新文檔,爲即將到來的發佈作各類準備。它就像是一個專門用來完善發佈的功能分支。
  • 一旦發佈準備穩妥,即將其併入 master 和 develop,而後刪除發佈分支。合併回 develop 很重要,由於可能已經有關鍵的更新添加到發佈分支上,而開發新功能須要用到它們。一樣的,若是團隊重視代碼審查,如今將是發起 pull request 的完美時機。

    git checkout master
    git merge release-0.1
    git push
    git checkout develop
    git merge release-0.1
    git push
    git branch -d release-0.1
  • 發佈分支是功能開發(develop)分支和公開發布(master)之間的過渡階段。不論何時,將提交併入 msater 時,你應該爲提交打上方便引用的標籤:

    git tag -a 0.1 -m "Initial public release" master
    git push --tags
  • Git 提供了許多鉤子,即倉庫中特定事件發生時被執行的腳本。當你向中央倉庫推送 master 分支或者標籤時,你能夠配置一個鉤子來自動化構建公開發布。

終端用戶發現一個 Bug

  • 正式發佈以後,兩個開發一塊兒爲下一個發佈開發功能。這時,一個終端用戶開了一個 issue 抱怨說當前發佈中存在一個 Bug。爲了解決這個 bug,先從 master 建立一個維護分支,用幾個提交修復這個 issue,而後直接合並回 master。

    git checkout -b issue*001 master
    ##Fix the bug
    git checkout master
    git merge issue-*001
    git push
  • 和發佈分支同樣,維護分支包含了 develop 中須要的重要更新,所以須要執行一樣的合併。接下來,能夠刪除這個分支:

    git checkout develop
    git merge issue-*001
    git push
    git branch -d issue-*001

各分支的意義

  • feature (多個) 主要是本身玩了,差很少的時候要合併回 develop 去。不與 master 交互。
  • develop (同時間一個) 主要是和 feature 以及 release 交互
  • release (同時間一個) 老是基於 develop,最後又合併回 develop。固然對應的 tag 要合併到 master 分支,生命週期短,僅是爲了發佈程序
  • hotfix (同一時間一個) 老是基於 master,並最後合併到 master 和 develop。生命同期較短,用來修復 bug 或小粒度修改發佈
  • master (僅一個) 關聯 tag 和發佈

模型中各個模塊內容的使用

  • 在這個模型中,master 和 develop 都具備象徵意義。master 分支上的代碼老是穩定的 (stable build),隨時能夠發佈出去。develop 上的代碼老是從 feature 上合併過來的,能夠進行 Nightly Builds,但不直接在 develop 上進行開發。當 develop 上的 featur 足夠多以至於能夠進行新版本的發佈時,能夠建立 release 分支。
  • release 分支基於 develop,進行委陰簡單的修改後就被合併到 master,並打上 tag,表示能夠發佈了。緊接着 release 將被合併到 develop;此時 Develop 可能往前跑了一段,出現合併衝突,須要手工解決衝突後再次合併,這步完成後就刪除 release 分支
  • 當從已發佈版本中發現 bug 要修復時,就應用到 hotfix 分支了。hotfix 基於 master 分支,完成 bug 修復或者緊急修改後,要 merge 回 master,打上一個新的 tag,並 merge 回 develop,刪除 hotfix 分支。
  • 因而可知 release 和 hotfix 的生命週期都較短,而 master 和 develop 雖然老是存在,但去不常使用。

文章首發於:https://www.zucchiniy.cn

相關文章
相關標籤/搜索