便於 Code review 的 Git 流程方案

網易考拉前端團隊發表於2017-10-17

設定讀者已經瞭解基本的 Git 操作和 Git 分支管理策略。

為了強化程式碼記錄的可讀性並協助 Code review 的執行,通過參考已有流程方案,設定一種適合的 Git 流程方案。

流程步驟

  1. 新建分支
  2. 提交 commit 記錄
  3. 合併 commit 記錄
  4. 推送到對應的遠端倉庫
  5. 提交 Merge Request 申請
  • 附:該流程的另一個好處:git cherry-pick
  • 附:使用 git pull --rebase 去掉多餘的 Merge Request

第一步:新建分支

每次開發新功能,都應該從當前主開發分支新建一個功能分支。

# 從當前分支新建功能分支,分支代號按照 JIRA 號設定
$ git checkout -b feature-KJDS-00000複製程式碼

第二步:提交 commit 記錄

新增功能後進行 commit,commit 時需要攜帶足夠的修改資訊。

# 新增到暫存區並完成提交
$ git add -A
$ git commit -m "header: some message"複製程式碼

這裡設定:

  • 雜項的提交使用 misc: 開頭:
$ git commit -m "misc: some awesome modification"複製程式碼
  • bugfix 或合併後的 commit 記錄使用 jira-No: 開頭:
$ git commit -m "jira-00001: fix a specific bug"複製程式碼

擴充:可以配合「gitmoji」強化資訊可讀性。

第三步:合併 commit 記錄

假設在 feature 功能分支上新增了 4 條開發記錄:

commit 34d364d9d51dc94b264e99f7a92add50dd2c3987
Author: Aeo <A_doz@126.com>
Date:   Sun Jun 25 12:27:02 2016 +0800

    misc: forth commit

commit 27322cb4b3f99226ffa98240460b90d92ed55a17
Author: Aeo <A_doz@126.com>
Date:   Sun Jun 25 12:26:42 2016 +0800

    misc: third commit

commit 405b957a96a7dbe352cf7da9a422312a735f6081
Author: Aeo <A_doz@126.com>
Date:   Sun Jun 25 12:26:16 2016 +0800

    misc: second commit

commit cc12fc86a7738ee2f9a8a48c31a9435232c2b08f
Author: Aeo <A_doz@126.com>
Date:   Sun Jun 25 12:25:53 2016 +0800

    misc: first commit複製程式碼

現在我們已經完成了 feature 分支的開發和聯調,需要把程式碼合併到當前主開發分支。

此時可以合併一些不必要的 commit 使主開發分支保持乾淨,優先推薦 git rebase 進行合併操作。

rebase:一般翻譯為「衍合」或「變基」

如果你想要合併最後 4 個 commit,你可以執行下列命令:

# -i 參數列示互動 (interactive)
$ git rebase -i HEAD~4複製程式碼

這時 git 會開啟一個互動介面,方便使用者對歷史提交進行修改:

pick cc12fc8 misc: first commit
pick 405b957 misc: second commit
pick 27322cb misc: third commit
pick 34d364d misc: forth commit

# Rebase 2763481..34d364d onto 2763481 (4 command(s))
#
# Commands:
# p, pick = 使用該提交
# r, reword = 使用該提交,但需要編輯提交資訊
# e, edit = 使用該提交,但此處暫停並提供修改機會
# s, squash = 使用該提交,但合併到上一個提交記錄中
# f, fixup = 類似 squash,但丟棄當前提交記錄的提交資訊
# x, exec = 執行 shell 命令
# d, drop = 移除當前提交複製程式碼

我們需要的是利用 squash 或者 fixup 進行分支合併:

pick cc12fc8 misc: first commit
squash 405b957 misc: second commit
squash 27322cb misc: third commit
squash 34d364d misc: forth commit複製程式碼

若使用 fixup 的話,則直接丟棄其它記錄,省去下一步操作。但使用 squash 時,則需要在下一步中對這 4 條 commit 資訊進行修改和儲存:

# This is a combinatin of 4 commits.
# This is the 1st commit message:

misc: first commit

# This is the commit message #2:

misc: second commit

# This is the commit message #3:

misc: third commit

# This is the commit message #4:

misc: forth commit複製程式碼

編輯並儲存後,通過 git log 可以看到僅剩一條 commit 記錄:

# 此時的 commit SHA 與之前的並不相同
commit da473276aa981f6e29577aa09a525109971547f2
Author: Aeo <A_doz@126.com>
Date:   Sun Jun 25 12:50:53 2016 +0800

    misc: first commit複製程式碼

rebase 的風險:

使用 rebase 需要遵循一條準則:

一旦分支中的提交物件釋出到公共倉庫,就千萬不要對該分支進行衍合操作。

簡單來說,當待合併 commit 記錄中雜糅著他人的 commit 記錄,此時就不可以再對這部分 commit 記錄做合併操作。

但只要新開分支且保持分支獨立開發,雜糅的情況就不存在。

第四步:推送到對應的遠端倉庫

完成 commit 記錄的合併後,此時可以反合目標分支的最新程式碼,避免後續提交 Merge Request 時存在衝突。

$ git push origin feature-KJDS-00000複製程式碼

第五步:提交 Merge Request 申請

當完成功能後提交到遠端後,需要經過下述流程:

  1. 提交 Merge Request:

    通過「+Create Merge Request」按鈕建立一個 Merge Request;

  2. 必須指定「Assignee」:

    指定需要 review 你程式碼的同學,禁止指定自己;

  3. 更改「Target branch」:

    改變為需要合併進去的目標分支;

  4. 設定合併後刪除被合併分支的選項:

    勾選「Remove source branch when merge request is accepted.」選項,在合併完成後刪除源分支,控制分支總數量;

  5. 使用「Submit Merge Request」提交合並請求。

完成上述設定後,相關同學將會收到郵件通知,此時可進入 GitLab 進行 code review。

如果發現問題則對問題程式碼進行點評並拒絕關閉申請,反之則通過合併申請。

合併申請通過後留下的 Merge Request 記錄,也就記錄了 code reviewer 。

附:該流程的另一個好處:git cherry-pick

通過該流程提交的程式碼,每個功能對應著唯一的提交記錄。

此時如果單獨提前上線部分功能,則可以在待上線分支中直接使用:

git cherry-pick commit-SHA複製程式碼

這裡的 commit-SHA 可以是其它分支上的提交記錄,此時可以直接將其抓到待上線分支上,避免從雜糅程式碼中扣取功能的時耗和風險。

附:使用 git pull --rebase 替代 git pull,去除多餘的 Merge Request

在專案初始搭建階段,可能需要多人同時在一個分支上進行開發,並有大量的併發操作,此時上述流程方案便不太適用。

但此時我們仍然可以利用 git pull --rebase 儘可能保持提交記錄清晰。

如果自己在本地 commit 了程式碼,然後執行 git pull,這時候極有可能出現這樣的合併記錄:

Merge branch 'feature' of ssh://domain/some-system into feature複製程式碼

但其實大部分情況下這裡是不會有衝突的。所以拉取遠端程式碼時,使用 git pull --rebase 就可以保持提交歷史記錄的整潔。

原理:把本地當前分支的未推送 commit 臨時儲存為補丁 (patch)(這些補丁放到 .git/rebase 目錄中),然後將遠端分支的程式碼拉取到本地,最後把儲存的這些補丁再應用到本地當前分支上。

若要把 rebase 當做 git pull 的預設值,可以修改 ~/.gitconfig 讓所有 tracked branches 自動使用該設定:

[branch]  
  autosetuprebase = always複製程式碼

附錄

  1. Git 分支的衍合
  2. Git 使用規範流程 - 阮一峰

相關文章