Git 版本控制(下)


前言

今天老闆叫我 把自己的 branch rebase development 的 branch,我真的是完全看不懂啊! 不過在稍微研究一下以後,發現 rebase 其實和 merge 的目的其實是一樣的,有鑑於 Git 版本控制(上) 已經累積了太大的篇幅,所以接下來有關 Git 的整理會集中在本篇。

merge vs. rebase

事前準備

首先創建一個資料夾並且開啟 git 版控

mkdir git_practice
cd git_practice
git init

接著創建一個 example.txt,在裡面寫上 我是第一行

vim example.txt

最後提交

git add example.txt
git commit -m "first commit"

目前為止的歷史紀錄像這樣子


我們在 example.txt 再新增一行 我是第二行

然後提交

git add example.txt
git commit -am "second commit"

目前為止的歷史紀錄像這樣子

複習 merge

事前工作準備好了以後我們要來創造平行的兩個分支,並且製造衝突

建立 task2 以及 task3 兩個分支並切換到 task2 分支。

git branch task2
git branch task3
git checkout task2

目前為止的歷史紀錄像這樣子


我們在 example.txt 再新增一行 我是 task2

然後提交

git add example.txt
git commit -am "task2 commit"


接著再切換到 task3 並在 example.txt 再新增一行 我是 task3

然後提交

git add example.txt
git commit -am "task3 commit"

到此為止我們完成了衝突的準備^^


fast-forward(快轉)合併

首先我們把 issue2 合併到 master,因為兩者並沒有衝突,所以會執行 fast-forward(快轉)合併,我們首先切換到 master 分支並合併 issue2 分支。

git checkout master
git merge task2


non-fast-forward(非快轉)合併

現在我們要合併 task3,這次會產生衝突,因為 master/task2 有 我是 task2 這一行但是 task3 的取而代之是 我是 task3

git merge issue3

合併失敗了,我們打開 example.txt 來查看衝突

我是第一行
我是第二行
<<<<<<< HEAD
我是 task2
=======
我是task3
>>>>>>> task3

我們將 example.txt 修改這樣

我是第一行
我是第二行
我是 task2
我是task3

最後再重新提交

git add myfile.txt
git commit -am "合併 task3"

rebase

現在讓我們退回到到衝突的狀態

git reset --hard HEAD~

現在我們切換到 task3 分支以後對 master 進行 rebase

git checkout task3
git rebase master

與 merge 的時候相同,我們一樣遇到了衝突無法合併的情況

我們打開 example.txt 來查看衝突

我是第一行
我是第二行
<<<<<<< HEAD
我是 task2
=======
我是task3
>>>>>>> task3

我們將 example.txt 修改這樣

我是第一行
我是第二行
我是 task2
我是task3

接著把 rebase 的流程繼續做完

git add example.txt
git rebase --continue

如果不想 rebase 了記得要 git rebase --abort

比較 merge 與 rebase 的差異

最重要的環節來了,不知道小夥伴們有沒有發現這兩種合併方法的差異,我們再重現一次。

merge

rebase

在 merge 的地方我們在解決衝突以後需要再產生一個新的 commit,但是為甚麼 rebase 不用呢?

在 rebase 的案例裡面我們從 task3 rebase master,而 rebase 的中文翻譯是「變基」,把從 task3 rebase master 翻成中文就是「我,就是 task3 分支,我現在要重新定義我的參考基準,並且將使用 master 分支當做我新的參考基準」,所以我們就注意到了,task3 與 master 叉開的 commit 被刪除了,task3 被接在了 master 的後面

merge 就比較好理解,分叉部分的 commit 都會被保留,只不過會有一個最新的 commit 來保留解決彼此衝突的部分~

補充: 在團隊協作中統一 commit 的樣式

由於最近開始在公司中與同事協作大型專案,便不能按照自己的風格隨意 commit,沒錯我就是亂 commit 的那一個人(笑,下面教各位讀者如何無痛整合專案成員的 commit 樣式 ~ !

寫一個有條不紊的 commit

像這樣一個 Commit 裡面包含了 HeaderBody,Header 不要超過一行,並且由 Type 以及 Subject 組合而成,Type 首先將 commit 的類型給分類; Subject 則試圖以扼要的文字總結 commit 做的事情;Body 可以多行,較為詳實的記錄了本次版本更新的內容。

依照 Angular 的規範,Type 有以下幾種:

feat: 新增/修改功能。
fix: 修補 bug。
docs: 文件 (documentation)。
style: 格式 (不影響程式碼運行 white-space, formatting, missing semi colons, etc)。
refactor: 重構。
perf: 改善效能。
test: 增加測試。
chore: 建構程序或輔助工具的變動 (maintain)。
revert: 撤銷回覆先前的 commit 例如:revert: type(scope): subject (回覆版本:xxxx)。

這樣一來,另一個閱讀的人便可以以不同的心態觀察程式碼,打個比方,如果 Type 是 Fix,可以用「觀察 Commit 如何解決錯誤」的角度來閱讀程式碼。

另外,建議不要一次將所有改動 commit,一次更新一個種類的 Type 並提交才可以讓 Commit 紀錄可以做好分類。

git config

git config 是 Git 提供的一個管理和設定組態參數的工具。等等的教學會用上它,因此我們先來認識它一下~

Git 參數的組態設定分為三個層級:

  1. 作業系統層級 (/etc/gitconfig)
  2. 使用者層級 (~/.gitconfig)
  3. 專案層級 (.git/config)

要調整系統層級的 config 要在參數帶上 --system、使用者層級要在參數帶上 --global、直接在專案內使用 git config 則會在專案層級設定。

Git 在查找組態時會由專案 > 使用者 > 作業系統層級依序查找。

開始實作

首先我們先創建一個空檔案準備存放 commit 的 template

touch .gitcommittemplate.txt

接著把這個檔案移動到目前使用者的根目錄下面

cp .gitcommittemplate.txt ~/.gitcommittemplate.txt

設定 git config 中 template 的位置(這邊也可以把層級設在使用者或是專案

git config --global commit.template ~/.gitcommittemplate.txt

為了確保 gitcommittemplate.txt 中的註解(#開頭的)也被寫進 commit message,這邊要再使用 git config 指令調整 commit 中的一些保留規則

git config --global commit.cleanup strip

strip 可以使得
Strip leading and trailing empty lines, trailing whitespace, commentary and collapse consecutive empty lines.

翻譯一下,設定 strip 可以刪除結尾與開頭的空白行、刪除每行末尾的空白、開頭帶有 # 的行,並且會把文中連續的空白行縮成一行空白。

最後打開 gitcommittemplate.txt

vim ~/.gitcommittemplate.txt

將 template 貼上

#git commit log
# <type>: <subject> {required}

# you need to give a blank line

# <body> {optional}

# <footer> {optional}

# <type>
# feat: 新功能
# fix: Bug修復
# docs: 文檔改變
# style: 代碼格式改變
# refactor: 功能重構
# perf: 性能優化
# test: 增加測試代碼
# build: 改變build工具
# ci: 與ci相關的設定
# add: 增加一些跟功能無關的檔案
# 3rd: 增加第三方
#
# <subject>
# 概括描述變動
#
# <body>
# 詳述改變內容,越詳細愈好
#
# <footer>
# 補充內容

這樣一來,下次在使用 git commit 的時候就可以直接用模板寫了(淚奔

上面的步驟如果很麻煩也可以寫成 bash 喔!

#merge #rebase #Git #變基 #合併






你可能感興趣的文章

關於 React 小書:props children 和容器類組件

關於 React 小書:props children 和容器類組件

propTypes、以 state 為中心去思考

propTypes、以 state 為中心去思考

Python Flask + Keras 建置圖片分類 API

Python Flask + Keras 建置圖片分類 API






留言討論