gitflow開發流程學習(第一部分)

gitflow開發流程學習(第一部分)

gitflow 流程是很是專業並且標準的 git 處理流程,由於要學習其核心思想和應用,故有此文章系列,本文章系列會分爲兩部分,第一部分學習基本的內容和基礎的流程,第二部分會學習其餘流程和hotfix,release 和 tag 之類的高級用法。html

1、gitflow 的分支學習

項目中長期存在的兩個分支:git

  • master:主分支,負責記錄上線版本的迭代,該分支代碼與線上代碼是徹底一致的。
  • develop:開發分支,該分支記錄相對穩定的版本,全部的feature分支和bugfix分支都從該分支建立。
在 gitlab 裏面能夠設置這2個分支的權限是受保護的,只容許某些人才能進行操做。

其它分支爲短時間分支,其完成功能開發以後須要刪除:github

  • feature/*:特性(功能)分支,用於開發新的功能,不一樣的功能建立不一樣的功能分支,功能分支開發完成並自測經過以後,須要合併到 develop 分支,以後刪除該分支。
  • bugfix/*:bug修復分支,用於修復不緊急的bug,普通bug均須要建立bugfix分支開發,開發完成自測沒問題後合併到 develop 分支後,刪除該分支。
  • release/*:發佈分支,用於代碼上線準備,該分支從develop分支建立,建立以後由測試同窗發佈到測試環境進行測試,測試過程當中發現bug須要開發人員在該release分支上進行bug修復,全部bug修復完後,在上線以前,須要合併該release分支到master分支和develop分支。
  • hotfix/*:緊急bug修復分支,該分支只有在緊急狀況下使用,從master分支建立,用於緊急修復線上bug,修復完成後,須要合併該分支到master分支以便上線,同時須要再合併到develop分支。

標準的流程以下圖:npm

clipboard.png

clipboard.png

由於這些圖涉及的流程太多,一會兒很難接受,因此須要逐個分解來學習。ruby

2、真實應用案例學習理解

項目背景:有一羣人共同開發一個 blog 系統。服務器

須要角色:網絡

  • 開發人員(負責代碼開發,包含新功能,修復 bug)
  • 開發人員leader(負責代碼 review,審覈代碼,合併代碼到 develop 和 master 分支)
  • 測試人員(測試檢查功能或者 bug 修復是否正常)
  • 部署人員(將代碼發佈到線上環境)

項目人員:app

  • 開發人員: a、b
  • 開發leader:c
  • 測試人員: d
  • 部署人員:e

項目分工:less

  • a 負責 articles 文章模塊,b 負責 login 登陸模塊
  • c 負責審覈和合並代碼(代碼 review和合並代碼到 develop 和 master 分支), a 和 b 開發的模塊代碼
  • d 須要等模塊開發完畢後,才能進行測試
  • 測試正常的狀況下,e 纔會執行部署

(一)基本開發流程

首先學習一個基本的流程,相似下圖,可是本次暫時不涉及 tag 處理:koa

clipboard.png

先建立一個服務端代碼倉庫,用 gitlab 來管理這個倉庫,名字叫作 blog-project,倉庫地址是git@xxx服務器地址/blog-project.git

項目剛開始,分支並不須要那麼多,在代碼倉庫裏只須要建兩個分支便可:

// 遠程服務器上代碼
master  // 默認主分支(受保護)
develop // 開發分支(受保護)

備註:

  • master 和 develop 分支是受保護分支,除了個別人員,例如 leader 外沒法操做。
  • 由於咱們使用的 gitlab,項目一開始能夠暫時手工操做項目的初始化信息,因此直接在界面創建分支,後期能夠不使用界面建立分支。

clipboard.png

開發者 clone 這個庫下來到本地:

// git 命令
git clone git@xxx服務器地址/blog-project.git

// clone 後每一個人的本地倉庫都以下:
master  // 默認主分支
develop // 開發分支

備註:

  • 全部相關參與的開發者都要 clone 這個庫。
  • 部署人員和測試人員按需 clone。

項目正式開始後,咱們須要分工開發,有如下兩種狀況咱們會遇到:

  1. 人手充足,時間充足,各自功能都能歸到各人頭上,而且可以很好的開發完成。

    1. a 單獨負責feature/articles功能。
    2. b 單獨負責feature/login功能。
  2. 人手不足,時間不充足,各自的功能可能須要各人混合開發,使用共享分支協力完成開發。
    1.feature/loginfeature/articles功能都成爲共享分支,全部人都參與開發

1. 針對第一種狀況:開發者 clone 遠端代碼倉庫後,不一樣的開發者進入不一樣的分支進行開發:

// 開發者 a 執行 git 命令
// 建立feature/articles 功能分支,並直接切換到該分支上進行開發
git checkout -b feature/articles

// 開發者 b 執行 git 命令
// 建立feature/login 功能分支,並直接切換到該分支上進行開發
git checkout -b feature/login

那麼如今開發者 a 和 b 本地的代碼庫以下:

// 開發者 a 
master  // 默認主分支
develop // 開發分支
feature/articles // 功能分支 articles 模塊

// 開發者 b
master  // 默認主分支
develop // 開發分支
feature/login // 功能分支 login 模塊

備註:

  • 由於 clone 整個項目,因此 master 和 develop 分支也會存在於本地,但由於受保護,因此沒法提交。
  • feature 相關分支是從 develop 分支拉取的,基點在當前的 develop head 位置。
  • 各自開發者不一樣的feature 功能分支,互不干涉。

開發完成後各自提交代碼到遠端代碼倉庫:

// 開發者 a
git add . // 添加當前目錄全部文件的改動到本地 git 倉庫
git commit --m "Add user API" // 須要按照 commit 規範,這個只是樣例
git push origin feature/articles // 

// 開發者 b
git add . // 添加當前目錄全部文件的改動到本地 git 倉庫
git commit --m "Add user API" // 須要按照 commit 規範,這個只是樣例
git push origin feature/login

備註:

  • 須要注意的是 commit 須要按照必定的規範來作,這些對整個項目都比較好,文章後面會徐徐道來。
  • 上例只是描述一個基本過程,開發代碼可能會屢次添加add和提交 push,這裏只是作一個示範。
  • git add 是添加文件到本地git倉庫緩衝區,換句話來講,是將有改動的文件放在本地的 git 代碼倉庫中,以便記錄版本和提交版本。

    • 上例只是描述一個基本過程,可是在開發的過程當中,可能只須要添加某個文件,不須要添交全部文件

2. 針對第二種狀況:開發者 clone 遠端代碼倉庫後,不一樣的開發者進入相同的分支進行開發(共享分支):

// 開發者 a 執行命令,切換到相應到分支
git fetch  // 取回遠端全部分支(branch)的更新
git checkout feature/articles // a 切換到feature/articles分支
git pull origin feature/articles // 拉取遠端feature/articles分支的全部更新到本地代碼
git checkout feature/login // a 切換到feature/login分支
git pull origin feature/login // 拉取遠端feature/login分支的全部更新到本地代碼

// 開發者 a 的本地代碼
master  // 默認主分支
develop // 開發分支
feature/articles // 功能分支 articles 模塊
feature/login // 功能分支 login 模塊
// 開發者 b 執行命令,切換到相應到分支
git fetch  // 取回遠端全部分支(branch)的更新
git checkout feature/articles // b 切換到feature/articles分支
git pull origin feature/articles // 拉取遠端feature/articles分支的全部更新到本地代碼
git checkout feature/login // b 切換到feature/login分支
git pull origin feature/login // 拉取遠端feature/login分支的全部更新到本地代碼

// 開發者 b 的本地代碼
master  // 默認主分支
develop // 開發分支
feature/articles // 功能分支 articles 模塊
feature/login // 功能分支 login 模塊

解釋:

  • 這裏feature/articles 分支和feature/login分支都會由開發者 a 或者 b 同時開發,由於是在共享分支開發,全部有可能會有共享衝突的問題, 在代碼開發以前, 應先更新好本地代碼倉庫,能夠減小衝突的發生。
  • 在共享分支開發的時候,有不少機會發生代碼合併衝突的,這個時候 git 會提醒開發者進行合和解決衝突(git merge conflict

備註:

  • 這裏先使用 fetch 的用意在這裏:與git pull相比git fetch至關因而從遠程獲取最新版本到本地,但不會自動merge。若是須要有選擇的合併git fetch是更好的選擇。

    • 因爲git pull把過程的細節都隱藏了起來,以致於你不用去了解git中各類類型分支的區別和使用方法。固然,多數時候這是沒問題的,但一旦代碼有問題,你很難找到出錯的地方。
    • 將下載(fetch)和合並(merge)放到一個命令裏的另一個弊端是,你的本地工做目錄在未經確認的狀況下就會被遠程分支更新。
    • 單獨進行下載和合並是一個好的作法,你能夠先看看區別(diff),而後再決定是否和本地代碼合併。並且分開來作,能夠清晰的區別開本地分支和遠程分支,方便選擇使用。因此儘可能少用git pull,多用git fetchmerge

3. 最終順利完成某個功能開發

開發者本地進行來基本的測試驗證,確認功能知足需求,而且沒有大的問題,而後會由開發者 leader 在 gitlab 上進行分支合併:

clipboard.png

由開發者 leader c 來進行合併,將feature/articlesfeature/login 分支合併到 develop 分支,合併完成後刪除源分支(feature/articlesfeature/login)。

至此使用基本流程完成開發。

3、備忘學習Commit規範和合並衝突解決

(一)關於合併衝突解決

  • 當Git沒法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。
  • 解決衝突就是把Git合併失敗的文件手動編輯爲咱們但願的內容,再提交。
  • 最簡單的編輯衝突的辦法,就是直接編輯衝突了的文件(test.txt),把衝突標記刪掉,把衝突解決正確。
發生衝突的地方不止 pull 還有 merge 和 rebase,只要發生合併的地方就可能會有衝突的發生。

如下例子以 git pull 來樣例:

// git pull 拉取代碼的時候發生衝突了
git pull XXXXX

// 報錯提示
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
// 衝突文件 test.txt 內容
a123
<<<<<<< HEAD
b789
=======
b45678910
>>>>>>> 6853e5ff961e684d3a6c02d4d06183b5ff330dcc
c

解釋:

  • 這個地方的提示意思是在文件 test.txt 內容中,在 a123和 c 之間有一個地方發生了衝突,有一部分是我修改的內容,有一部分是別人修改的內容。
  • 其中:衝突標記<<<<<<<=======之間的內容是個人修改,=======>>>>>>>之間的內容是別人的修改。

    • 若是保留個人修改,那麼刪掉別人的修改便可。
    • 反之亦然。
    • 若是各取一半,那麼你能夠將他們所有提取出來,刪掉不須要的,改掉不符合的,而後再放回去。

備註:

  • 若是沒法確認是否有衝突,也不想執行一次 pull來觸發檢查,可使用git status命令查看。
// 執行 git 命令
git status

// 輸出提示
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)
// 你能夠放棄合併,git merge --abort 選項會嘗試恢復到你運行合併前的狀態。
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
// 衝突的文件
    both modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")
  • 你能夠經過 git diff --base來查看文件在兩邊是如何改動的。
// 執行 git 命令
git diff --base -b  // -b 是爲了去除空白內容

// 輸出信息
* Unmerged path hello.rb
// 結果爲git格式的diff。
// 進行比較的是,a版本的f1(即變更前)和b版本的f1(即變更後)。
diff --git a/hello.rb b/hello.rb
index ac51efd..44d0a25 100755
// "---"表示變更前的文件,"+++"表示變更後的文件。
--- a/hello.rb
+++ b/hello.rb
// 前面的"-1,7"分紅三個部分:減號表示第一個文件(即f1),"1"表示第1行,"7"表示連續7行。合在一塊兒,就表示下面是第一個文件從第1行開始的連續7行。一樣的,"+1,8"表示變更後,成爲第二個文件從第1行開始的連續9行
@@ -1,7 +1,8 @@
// 文件內容的每一行最前面,還有一個標記位。若是爲空,表示該行無變化;若是是感嘆號(!),表示該行有改動;若是是減號(-),表示該行被刪除;若是是加號(+),表示該行爲新增。
 #! /usr/bin/env ruby

+# prints out a greeting
 def hello
-  puts 'hello world'
+  puts 'hello mundo'
 end

 hello()
  • 若是有強烈意願只保留本身的代碼的狀況下也是能夠的:

    • 使用gitpush origin master --forcegitpush origin master -f。可是這種方式存在覆蓋掉其餘人提交的危險,當肯定不會影響到其餘人提交的狀況下可使用,好比使用gitcommit –amend修改提交日誌等狀況。

(二)Commit規範

爲何須要 commit 規範?主要是爲了看清楚每次 commit 的內容,清楚知道 commit 變更的地方,從而方便排錯和控制代碼。

1. commit 的原則:

  • 提交時的粒度是一個小功能點或者一個 bug fix,這樣進行恢復等的操做時可以將「誤傷」減到最低。
  • 用一句簡練的話寫在第一行,而後空一行稍微詳細闡述該提交所增長或修改的地方。
  • 不要每提交一次就推送一次,多積攢幾個提交後一次性推送,這樣能夠避免在進行一次提交後發現代碼中還有小錯誤。
  • commit 規範的內容規則以下:
// 提交類型
feat: 添加新特性
fix: 修復bug
docs: 僅僅修改了文檔
style: 僅僅修改了空格、格式縮進、都好等等,不改變代碼邏輯
refactor: 代碼重構,沒有加新功能或者修復bug
perf: 增長代碼進行性能測試
test: 增長測試用例
chore: 改變構建流程、或者增長依賴庫、工具等

// 提交範圍 scope
scope用於說明 commit 影響的範圍,好比數據層、控制層、視圖層等等,視項目不一樣而不一樣。

// 提交的subject內容
subject是 commit 目的的簡短描述,不超過50個字符。
以動詞開頭,使用第一人稱如今時,好比change,而不是changed或changes
第一個字母小寫,結尾不加句號(.)

// 提交的 body 內容
Body 部分是對本次 commit 的詳細描述,能夠分紅多行。

2. 一個標準且優美的 git 提交記錄圖應該是這樣的:

clipboard.png

3. 要實現規範的 commit 則須要安裝一些工具來簡化操做:

  • npm install -g commitizen 這個是一個格式化commit message的工具。
  • npm install -g conventional-changelog-cli 這個是生成changelog的工具,changelog 是爲了將這些格式化的 commit message 生成一個 CHANGELOG.md文件的,這個文件能夠規範看到提交的內容(如上圖一個標準且優美的 git 提交記錄圖)。

4. 執行過程:

// 執行git 命令
git cz 

// 輸出  
cz-cli@2.10.1, cz-conventional-changelog@2.1.0

Line 1 will be cropped at 100 characters. All other lines will be wrapped after 100 characters.
// 提示輸入你的 commit類型,他會彈出提示給你選擇
? Select the type of change that you're committing: fix:      A bug fix
// 提示輸入你的 scope類型,沒有能夠跳過
? What is the scope of this change (e.g. component or file name)? (press enter to skip)
 test
// 提示輸入你的 subject,即標題
? Write a short, imperative tense description of the change:
 我來測試這個 commit 格式
// 提示輸入你的 body 內容,就是詳細信息
? Provide a longer description of the change: (press enter to skip)
 詳細
? Are there any breaking changes? No
// 當你有使用 issues 的時候就會關聯到 issues
? Does this change affect any open issues? No
[master a4fd22c] fix(test): 我來測試這個 commit 格式
 3 files changed, 14 insertions(+), 1 deletion(-)

提交記錄會變成這樣(使用 git log 命令能夠查看):

// 輸出結果是
fix(test): 我來測試這個 commit 格式
詳細

至於 CHANGELOG.md內容則以下:

<a name="1.0.0"></a>
# 1.0.0 (2017-03-05)
### Bug Fixes
* fixed ([a9c3110](https://192.168.2.107/zpu/hello-koa/commits/a9c3110))
### Features
* add something ([53becaa](https://192.168.2.107/zpu/hello-koa/commits/53becaa))

解析 md 文件以後,會很清晰的知道每一個版本或者提交都負責了那些內容,相似這樣:

clipboard.png

本文參考到的資料地址:

文章轉自 gitflow 開發流程學習(第一部分)

相關文章
相關標籤/搜索