使用 Gitflow 工具讓你的開發專案控制工作流程

通常你都是怎麼管理開發的分支以及版號的呢?隨著開發的功能越來越多,協作的開發人員也增加,漸漸的發現 git 在管理上多出越來越多隻 branch,經常要 merge 檔案,衝突到的程式碼段又要一個一個整理&解開…。不希望在亂亂的分支搞不清楚現在開發到哪裡了,無不希望自己的專案上的 git 可以有效率的在同一個概念下管理所有的分支,直到某天看到了這個 gitflow 的特性跟介紹,到底能省下我們多少工作流程與時間,於是就研究看看…

看到這裡,是不是已經覺得深有同感,下面具體介紹 gitflow 工作流:

什麼是 gitflow

Gitflow 是一個 Git 分支的模型,通常包含 master, develop, feature, release, hotfix,各自負責不同功能,其中 master 與 develop 是遠端的分支,而 feature, release, hotfix 是本地分支,任務結束就會被刪除。可以看到一張 gitflow 流程圖:

| Master 分支 |

主要作為唯一正式對外發布的分支,只能從別的分支合併。當版本發佈之後,通常會為這個 master 分支補上版本號的標籤。

| Develop 分支 |

作為所有開發的主分支,永遠是功能最新的分支,是根據 master 分支建立出來,算是集中開發完成的特性,通常也有很多詳細跟完整的提交敘述,當 feature 功能開發完成,會合併到 develop ,然而也刪除 feature 分支。

| Feature 分支 |

是從 develop 分支建立的,除了開發人員的 local 本地之外,也可以推送到遠端的 git repo 位置,可以當作工作備份,或是讓其他開發者使用。完成之後會再合併回 develop 分支。

建立 feature 分支

在一般原本作法的情況,當你不使用 gitflow 時,是不是都從 master 先 checkout 一支 develop branch,再從 develop 切一隻 feature_notify 來開發功能。

1
2
$ git checkout develop
$ git checkout -b feature_notify

但,當你使用 gitflow 工具,只要輸入以下這方式,就可以自動的在 develop 分支一條 feature_notify 分支

1
$ git flow feature start feature_notify

完成 feature 分支

好的,你總是會在 feature_notify 分支開發,當你開發完畢之後,下一個動作就是再到 develop 合併 feature_notify 分支

當你不使用 gitflow 時

1
2
$ git checkout develop
$ git merge feature_notify

但,當你使用 gitflow 工具,只要輸入以下這方式,此時就會完成的功能,合併到 develop 之中,並且刪除做好的 feature

1
$ git flow feature finish feature_notify

| Release 分支 |

如果你覺得 develop 分支已經足以發佈釋出時,就可以把它合併到 release 分支,也當作上線之前的最後測試。

當你不使用 gitflow 時

1
2
$ git checkout develop
$ git checkout -b release/0.1.0

但,當你使用 gitflow 時,這時就會合併到 master, develop 當中了。原本發布的這隻 release 也會被刪除。在這個 release start 階段,是你已經差不多確認上線前的測試

1
2
$ git flow release start 0.1.0
Switched to a new branch 'release/0.1.0'

確定好準備發佈之後,就用 release finish 來完成

當你不使用 gitflow 時,

1
2
$ git checkout master
$ git merge release finish '0.1.0'

但,當你使用 gitflow:

1
$ git flow release finish '0.1.0'

| Hotfix 分支 |

是直接從 master 分支建立,為了快速的修補 bug 已經上線的版本,當修好功能之後,可以合併到 master 和 develop 以及 release 分支,並在 master 打上標籤

建立 hotfix

當你不使用 gitflow 時,

1
2
$ git checkout master
$ git checkout -b hotfix_notify

但,當你使用 gitflow:

1
$ git flow hotfix start hotfix_notify

完成 hotfix

當你不使用 gitflow 時,

1
2
3
4
5
$ git checkout master
$ git merge hotfix_notify
$ git checkout develop
$ git merge hotfix_notify
$ git branch -D hotfix_notify

但,當你使用 gitflow:

1
$ git flow hotfix finish hotfix_notify

看起來 gitflow 指令簡單又俐落,觀念理解指令自然容易操作

試試如何操作實現 gitflow 工作流方法?

上述大致上介紹之後,接下來我們就利用這個工具實際操作整個 gitflow 工作流的方法。如果你在 ubuntu 環境,就在命令提示字元輸入

1
2
$ apt-get update
$ apt-get install git-flow

步驟一:在 gitlab 新增一個遠端的 repo 位置、並且 clone 到本地

1
$ git clone http://192.168.12.11/test/test-gitflow.git

步驟二:新增一個檔案並且開始提交

1
2
3
4
5
6
7
$ touch README
$ git add README
$ git commit -am 'init'

[master (根提交) 67bdda0] init
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README

將提交推到遠端

1
2
3
4
5
6
7
8
$ git push

枚舉物件: 3, 完成.
物件計數中: 100% (3/3), 完成.
寫入物件中: 100% (3/3), 200 位元組 | 200.00 KiB/s, 完成.
總共 3 (差異 0),復用 0 (差異 0),重用包 0
To http://192.168.12.11/test/test-gitflow.git
* [new branch] master -> master

接著我們就用這個當前的工作目錄開始 gitflow

步驟三:在本地端的工作目錄執行 git flow init ,開始初始化 gitflow ,初始化的過程會詢問一些問答,大致上都可以維持預設配置,這時候命令完成之後,就可以看到出現兩個 master 以及 develop 分支。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git flow init

Which branch should be used for bringing forth production releases?
- master
Branch name for production releases: [master]
Branch name for "next release" development: [develop]

How to name your supporting branch prefixes?
Feature branches? [feature/]
Bugfix branches? [bugfix/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Hooks and filters directory? [~/Workspaces/projects/test-gitflow/.git/hooks]

這時候會呈現把原本在 master 的分支,切到 develop 分支

1
2
3
4
5
$ git branch

* develop
master
(END)

步驟四:試想著,接下來要開發一個新產品功能,那麼執行 git flow feature start 的指令,這個會自動的從 develop 建立一個 feature/products 分支,這時候就切到新的分支

1
2
3
4
5
6
7
8
9
10
11
$ git flow feature start products

切換到一個新分支 'feature/products'

Summary of actions:
- A new branch 'feature/products' was created, based on 'develop'
- You are now on branch 'feature/products'

Now, start committing on your feature. When done, use:

git flow feature finish products

那麼,我們在這個分支在 README 檔案增加一點敘述

1
2
3
4
5
6
7
$ vi README
$ cat README
this is my new product feature.

$ git commit -am "new feature on product branch"
[feature/products 88b2783] new feature on product branch
1 file changed, 1 insertion(+)

這個 feature 分支,可以推到遠端讓其他人可以 pull 來使用。試著推上去

1
2
3
4
5
6
7
8
$ git push origin feature/products

枚舉物件: 5, 完成.
物件計數中: 100% (5/5), 完成.
寫入物件中: 100% (3/3), 276 位元組 | 276.00 KiB/s, 完成.
總共 3 (差異 0),復用 0 (差異 0),重用包 0
To http://192.168.12.11/test/test-gitflow.git
* [new branch] feature/products -> feature/products

步驟五:某一位開發者需要緊急修復訂單的 bug ,他也 clone 這個 repo 到本地端。需要立刻執行 git flow hotfix start 指令,這時候就會立刻從 master 新建一個 hotfix/order 分支出來,然後當前的分支就是 hotfix/order

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git flow hotfix start order

切換到一個新分支 'hotfix/order'

Summary of actions:
- A new branch 'hotfix/order' was created, based on 'master'
- You are now on branch 'hotfix/order'

Follow-up actions:
- Start committing your hot fixes
- Bump the version number now!
- When done, run:

git flow hotfix finish 'order'

那麼就假設新增一個 order.txt 檔案做緊急修復的功能檔案

1
2
3
4
5
6
7
$ touch order.txt
$ git add order.txt
$ git commit -am "add order.txt"

[hotfix/order 67376b3] add order.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 order.txt

在 hotfix 是可以推送到遠端,也可以讓其他的開發者 pull 使用

1
2
3
4
5
6
7
8
9
10
$ git push origin hotfix/order

枚舉物件: 3, 完成.
物件計數中: 100% (3/3), 完成.
使用 8 個執行緒進行壓縮
壓縮物件中: 100% (2/2), 完成.
寫入物件中: 100% (2/2), 240 位元組 | 240.00 KiB/s, 完成.
總共 2 (差異 0),復用 0 (差異 0),重用包 0
To http://192.168.12.11/test/test-gitflow.git
* [new branch] hotfix/order -> hotfix/order

當你確定修復都沒問題的話,那麼再執行 git flow hotfix finish 指令,在這裡就會開始詢問一些資訊,合併的解釋

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ git flow hotfix finish order

切換到分支 'master'
您的分支與上游分支 'origin/master' 一致。
Merge made by the 'ort' strategy.
order.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 order.txt

切換到分支 'develop'
Merge made by the 'ort' strategy.
order.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 order.txt

To http://192.168.12.11/test/test-gitflow.git
- [deleted] hotfix/order
已刪除分支 hotfix/order(曾為 67376b3)。

Summary of actions:
- Hotfix branch 'hotfix/order' has been merged into 'master'
- The hotfix was tagged 'order'
- Hotfix tag 'order' has been back-merged into 'develop'
- Hotfix branch 'hotfix/order' has been locally deleted; it has been remotely deleted from 'origin'
- You are now on branch 'develop'

這時候會把 hotfix/order 分支的工作合併到 master 以及 develop 分支,然後在 master 加上 hotfix 標籤,再把原本的本地端跟遠端刪掉,最後你看到的工作位置會在 develop

還記得前面 feature/products 分支嗎?這時候開發完畢了,那麼就執行 git flow feature finish 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git flow feature finish products

已經位於 'develop'
Merge made by the 'ort' strategy.
README | 1 +
1 file changed, 1 insertion(+)

To http://192.168.12.11/test/test-gitflow.git
- [deleted] feature/products
已刪除分支 feature/products(曾為 88b2783)。

Summary of actions:
- The feature branch 'feature/products' was merged into 'develop'
- Feature branch 'feature/products' has been locally deleted; it has been remotely deleted from 'origin'
- You are now on branch 'develop

這裡會把 products 分支合併到 develop 分支,再把原本的本地端跟遠端刪掉,最後你看到的工作位置會在 develop

步驟六:products 分支終於可以發布功能了,執行 git flow release start 會把 develop 的分支建立一個 0.1.0 版本的分支,這個主要是用來預備發佈使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git flow release start 0.1.0

切換到一個新分支 'release/0.1.0'

Summary of actions:
- A new branch 'release/0.1.0' was created, based on 'develop'
- You are now on branch 'release/0.1.0'

Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run:

git flow release finish '0.1.0'

會自動新增一個 release/0.1.0 的分支,這個位置是不能再增加功能的,但可以修改 bug、也可以遠端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ vi README
$ git commit -am "update on release/0.1.0"

[release/0.1.0 784ac1d] update on release/0.1.0
1 file changed, 2 insertions(+)

$ git push origin release/0.1.0

枚舉物件: 14, 完成.
物件計數中: 100% (14/14), 完成.
使用 8 個執行緒進行壓縮
壓縮物件中: 100% (10/10), 完成.
寫入物件中: 100% (12/12), 1.34 KiB | 1.34 MiB/s, 完成.
總共 12 (差異 2),復用 0 (差異 0),重用包 0
To http://192.168.12.11/test/test-gitflow.git
* [new branch] release/0.1.0 -> release/0.1.0

差不多修好了嗎?那麼我們繼續執行 git flow release finish 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ git flow release finish 0.1.0

Branches 'master' and 'origin/master' have diverged.
And local branch 'master' is ahead of 'origin/master'.
切換到分支 'master'
您的分支領先 'origin/master' 共 2 個提交。
(使用 "git push" 來發布您的本機提交)
Merge made by the 'ort' strategy.
README | 3 +++
1 file changed, 3 insertions(+)
已經位於 'master'
您的分支領先 'origin/master' 共 7 個提交。
(使用 "git push" 來發布您的本機提交)
切換到分支 'develop'
Merge made by the 'ort' strategy.
README | 2 ++
1 file changed, 2 insertions(+)

To http://192.168.12.11/test/test-gitflow.git
- [deleted] release/0.1.0
已刪除分支 release/0.1.0(曾為 784ac1d)。

Summary of actions:
- Release branch 'release/0.1.0' has been merged into 'master'
- The release was tagged '0.1.0'
- Release tag '0.1.0' has been back-merged into 'develop'
- Release branch 'release/0.1.0' has been locally deleted; it has been remotely deleted from 'origin'
- You are now on branch 'develop'

這個方式會把 release/0.1.0 分支合併到 master, develop,也會把本地端跟遠端的刪除。最後,也是會切到 develop 分支。如此一來就完成了開發 cycle 的流程囉。有了這個標準套用在你的所有 git 流程工作上,相信你後透過簡單的流程解決複雜的工作問題。

參考資料

Git工作流面面观——Gitflow工作流