Git Flow

Git Flow:一个成功的分支模型,它在使用分支引入功能的许多较大项目中变得流行起来。

Feature branches

Feature branches:git flow 中的关键点是创建和使用功能分支。它们的目的是允许并行(或独立)的功能开发,随后可以合并回一个整合的分支。当然,Git 特别适合这项任务,因为可以自由创建分支,然后轻松进行合并。

Feature branches最终合并回主开发分支,称为git flow中的 developgit merge --no-ff 的关键点在于,即使开发分支可以进行快进合并,它也会给你一个合并节点。这个合并节点允许你确定首先在哪个分支创建修复。

尽管许多人认为“功能”是一个广义的术语,事实上,也完全有可能考虑微型功能。一些开发人员会为每个提交的错误创建一个新的功能分支,这样可以在 bug 跟踪器中保留与提交错误有关的链接(你也可以使用任意的提交消息来启用这种链接)。

Release branches

Release branches::一旦开发分支准备发布,就会创建一个(预)发布分支。然后,该分支仅用于该发布的错误修复(这些错误修复会合并回 develop 分支),以准备最终的标记。每个分支都以其版本号命名;因此,release-1.0 将是用于在 1.0 版本发布之前开发代码的分支。一旦 1.0 版本的开发完成,将对其进行标记,并停止在 release-1.0 分支上的工作(Git Flow 建议此时删除分支,以防止意外进一步的工作。由于已经标记,如果需要,可以轻松重新创建)。

Hotfix branches

Hotfix branches:可能需要迅速启动一个新的发布(有时也被称为补丁发布)以解决生产问题,但在下一个主要(或次要)发布之前。热修复分支也以发布命名(例如 hotfix-1.0.1),仅包含该版本的特定错误修复。更改会合并回 develop 分支,以确保错误也在后续版本中得到修复。通常,热修复分支上一次只有几次提交,因为它们通常会合并回发布分支。

分支命名

分支名字并不真正改变你使用 Git 可以实现的功能;毕竟,你可以轻松地从标签和分支中创建一个分支。实际上git flow 模型建议在 develop 分支上完成工作,而不是在主分支(通常是 Git 开发的主要分支)上完成工作——在 git flow 中,master 分支仅保留用于已发布的标签。

然而,一个关键点是合并节点会存储它们合并自的分支的名称。这意味着如果使用分支名称,你可以追踪一个功能从功能分支流经 develop 分支最终到达发布分支的过程。

为了演示它在实践中是如何工作的,这里是 Git Flow 中开发的一个缩短序列以及结果合并树。

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
29
30
31
32
33
34
35
36
37
38
39
40
(master) $ git log --oneline
4f5da46 Initial Commit
(master) $ git checkout -b develop
Switched to a new branch 'develop'
(develop) $ …
(develop) $ git checkout -b feature1 develop
Switched to a new branch 'feature1'
(feature1) $ …
(feature1) $ git checkout -b feature2 develop
Switched to a new branch 'feature2'
(feature2) $ …
(feature2) $ git checkout develop; git merge --no-ff feature2
Merge made by recursive.

(develop) $ git checkout develop; git merge --no-ff feature1
Merge made by recursive.

(develop) $ git checkout -b release-1.0 develop # ready for 1.0
Switched to a new branch 'release-1.0'
(release-1.0) $ echo 1.0 > version; git add version; git commit -m "Version 1.0" version
[release-1.0 c51b802] Version 1.0
(release-1.0) $ git checkout master
Switched to branch 'master'
(master) $ git merge --no-ff release-1.0
Merge made by recursive.
(master) $ git tag -a 1.0 # tag the release once it's finished
(master) $ git checkout -b hotfix-1.0.1 master # create a hotfix for 1.0
Switched to a new branch 'hotfix-1.0.1'
(hotfix-1.0.1) $ echo 1.0.1 > version; git add version; git commit -m "Version 1.0.1"

(hotfix-1.0.1) $ git checkout master
Switched to branch 'master'
(master) $ git merge --no-ff hotfix-1.0.1
Merge made by recursive.
(master) $ git checkout develop # merge the hotfix back into 'develop'
Switched to branch 'develop'
(develop) $ git merge --no-ff hotfix-1.0.1
Merge made by recursive.
(develop) $ git branch -d hotfix-1.0.1
Deleted branch hotfix-1.0.1 (was f43bb33).

尽管上述的编辑并没有包含任何真正的工作,但合并的关键点使我们能够生成这个合并树:

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
29
30
31
32
33
34
35
36
37
38
(develop) $ git log --decorate --graph --oneline
* 17e4c5f (HEAD, develop) Merge branch 'hotfix-1.0.1' into develop
|\
| * f43bb33 (hotfix-1.0.1) Hotfix2
| * 50a102d Hotifx1
| * d2fe7d6 Version 1.0.1
| * d534111 (tag: 1.0) Merge branch 'release-1.0'
| |\
* | \ 77e7eac Merge branch 'release-1.0' into develop
|\ \ \
| | |/
| |/|
| * | 9261fad (release-1.0) Release10Fix2
| * | 2562cb3 Release10Fix1
| * | c51b802 Version 1.0
* | | fbdd638 Work6
* | | 7353285 Work5
|/ /
* | 538bb9a Work4
* | cdef254 Merge branch 'feature1' into develop
|\ \
| * | 793b1bc (feature1) Feature1Work4
| * | 3f2be07 Feature1Work3
| * | 7879593 Feature1Work2
| * | 8e01f4d Feature1Work1
* | | 9239c56 Merge branch 'feature2' into develop
|\ \ \
| |_|/
|/| |
| * | 6752543 (feature2) Feature2Work3
| * | d065311 Feature2Work2
| * | 040fcaf Feature2Work1
| |/
| * a9a97be Work3
| * a4253c8 Work2
| * 163c835 Work1
|/
* 4f5da46 Initial Commit

这可能看起来有点杂乱,但我们可以通过使用 git log--merges 标志将其压缩,这样我们只能看到合并节点:

1
2
3
4
5
6
(develop) $ git log --decorate --graph --oneline --merges
* 17e4c5f (HEAD, develop) Merge branch 'hotfix-1.0.1' into develop
| * d534111 (tag: 1.0) Merge branch 'release-1.0'
* 77e7eac Merge branch 'release-1.0' into develop
* cdef254 Merge branch 'feature1' into develop
* 9239c56 Merge branch 'feature2' into develop

此时,使用 –no-ff 的好处变得明显;这是一种记录合并的方法,以便可以通过 git log 命令进行过滤。此外,Git Flow 的命名约定使我们能够识别图表中的一组良好描述的功能和发布分支。

无论 Git Flow 是否适合你现在,了解它是什么(以及为什么它遵循这条路径)都是值得的。即使现在对你不适用,随着你的存储库规模的扩大和对 git 的使用增加,将来可能值得回头看一看。GitHub 仓库中还有一组脚本,可以使管理各个分支变得更容易。