1
1
# Git 工作流程
2
2
3
- 基于一个流行的 [ 项目开发指南] ( https://github.com/elsewhencode/project-guidelines ) ,本文描述了一个建议的 github 工作流程。具体项目可以定制工作流程。项目初期可以采用简化的工作流。比如,一个项目在初期只有一、二个人的时候,所有操作都在 master 分支 -- 但是上线前必须有 develop 分支。
3
+ 基于一个流行的 [ 项目开发指南] ( https://github.com/elsewhencode/project-guidelines ) ,本文描述了一个建议的 github 工作流程。和上述指南最大的不同是我们采用 master 分支作为主开发分支。另外创建专门的上线发布 release 分支。这样的好处是 master 在 github 是缺省的分支,变基,PR 和合并都比较自然。而且上线发布分支只有少数人关注,对开发人员越隐蔽越好。
4
+
5
+ 具体项目可以定制工作流程。项目初期可以采用简化的工作流。比如,一个项目在初期只有一、二个人的时候,所有操作都在 master 分支 -- 但是上线前必须有 release 分支。
4
6
5
7
分支类型:
6
8
7
- - Master 分支:该分支在第一次上线之后,永远保持可随时上线状态,不允许直接在这个上面进行更改或者提交代码,只能从其他分支 merge
8
- - develop 分支:原则上,develop 分支主要用于新版本的开发,代码第一次上线后 ,从 master 创建出 develop 分支,后期版本开发在此之上进行, 版本开发完毕之后,上线前,将 develop merge 到 master ,并做上线测试
9
- - 功能分支:每个版本的开发,会有很多独立功能,每个独立功能的开发,从 develop 创建一个功能分支,并在功能分支上进行功能的开发,最后合并到 develop
10
- - hotfix 分支:这种类型的分支是针对线上 bug 的紧急 fix,直接从 master 创建分支, 修复,测试完毕之后,合并到 master,并上线
9
+ - release 分支:该分支在第一次上线之后,永远保持可随时上线状态,不允许直接在这个上面进行更改或者提交代码,只能从其他分支 merge
10
+ - master 分支:master 分支主要用于新版本的开发,代码第一次上线时 ,从 master 创建出 release 分支用于上线发布。所有后期版本开发都在 master 分支上进行。 版本开发完毕之后,上线前,将 master 的修改合并到 release ,并做上线测试
11
+ - 功能分支:每个版本的开发,会有很多独立功能,每个独立功能的开发,从 master 创建一个功能分支,并在功能分支上进行功能的开发,最后变基合并到 master。
12
+ - hotfix 分支:这种类型的分支是针对线上 bug 的紧急 fix,直接从 release 创建分支。 修复,测试完毕之后,合并到 release 上线。然后相应应该也并入 master 分支。
11
13
12
14
一些原则:
13
15
14
16
- PR 每个 PR 都只是针对一个功能,不能够太大, 原则上不超过 10 个文件
15
17
16
- ## 1. 一些原则
18
+ ## 1. 基本规则
17
19
18
20
这里有一套规则要牢记:
19
21
23
25
24
26
> 因为这样,所有的工作都是在专用的分支而不是在主分支上隔离完成的。它允许您提交多个 pull request 而不会导致混乱。您可以持续迭代提交,而不会使得那些很可能还不稳定而且还未完成的代码污染 master 分支。
25
27
26
- - 从 ` develop ` 独立出分支。
28
+ - 从 ` master ` 独立出分支 ` release ` 分支用于上线发布 。
27
29
28
30
为什么
29
31
30
- > 这样,您可以保持 ` master ` 分支中的代码稳定性,这样就不会导致构建问题,并且几乎可以直接用于发布(当然,这可能对某些项目来说要求会比较高) 。
32
+ > 这样,您可以保持 ` release ` 分支中的代码稳定性,随时可以直接用于发布 。
31
33
32
- - 永远也不要将分支(直接)推送到 ` develop ` 或者 ` master ` ,请使用合并请求(Pull Request)。
34
+ - 永远也不要将分支(直接)推送到 ` master ` ,请使用合并请求(Pull Request)。
33
35
34
36
为什么
35
37
36
38
> 通过这种方式,它可以通知整个团队他们已经完成了某个功能的开发。这样开发伙伴就可以更容易对代码进行 code review,同时还可以互相讨论所提交的需求功能。
37
39
38
- - 在推送所开发的功能并且发起合并请求前,请更新您本地的` develop ` 分支并且完成交互式变基操作(interactive rebase)。
40
+ - 在推送所开发的功能并且发起合并请求前,请更新您本地的` master ` 分支并且完成交互式变基操作(interactive rebase)。
39
41
40
42
为什么
41
43
42
- > rebase 操作会将(本地开发分支)合并到被请求合并的分支( ` master ` 或 ` develop ` )中,并将您本地进行的提交应用于所有历史提交的最顶端,而不会去创建额外的合并提交(假设没有冲突的话),从而可以保持一个漂亮而干净的历史提交记录。 [ 合并(merge)和变基(rebase)的比较] ( https://www.atlassian.com/git/tutorials/merging-vs-rebasing )
43
-
44
- - 请确保在变基(rebase)并发起合并请求之前解决完潜在的冲突。
44
+ > rebase 操作会将功能合并到被请求合并的 master 分支,并将您本地进行的提交应用于所有历史提交的最顶端,而不会去创建额外的合并提交(假设没有冲突的话),从而可以保持一个漂亮而干净的历史提交记录。 [ 合并(merge)和变基(rebase)的比较] ( https://www.atlassian.com/git/tutorials/merging-vs-rebasing )
45
45
46
- - 合并分支后删除本地和远程功能分支。
46
+ - 请确保在变基(rebase)并发起合并请求之前解决完潜在的冲突, 合并分支后删除本地和远程功能分支。
47
47
48
48
为什么
49
49
50
- > 如果不删除需求分支,大量僵尸分支的存在会导致分支列表的混乱。而且该操作还能确保有且仅有一次合并到` master ` 或 ` develop ` 。只有当这个功能还在开发中时对应的功能分支才存在。
50
+ > 如果不删除需求分支,大量僵尸分支的存在会导致分支列表的混乱。而且该操作还能确保有且仅有一次合并到` master ` 。只有当这个功能还在开发中时对应的功能分支才存在。
51
51
52
52
- 在进行合并请求之前,请确保您的功能分支可以成功构建,并已经通过了所有的测试(包括代码规则检查)。
53
53
54
54
为什么
55
55
56
56
> 因为您即将将代码提交到这个稳定的分支。而如果您的功能分支测试未通过,那您的目标分支的构建有很大的概率也会失败。此外,确保在进行合并请求之前应用代码规则检查。因为它有助于我们代码的可读性,并减少格式化的代码与实际业务代码更改混合在一起导致的混乱问题。
57
57
58
- - 保护您的 ` develop ` 和 ` master ` 分支 。
58
+ - 保护您的 ` master ` ,尤其是 ` release ` 分支改动需要特别授权 。
59
59
60
60
为什么
61
61
62
62
> 这样可以保护您的生产分支免受意外情况和不可回退的变更。
63
63
64
64
## 2. 建议的工作流
65
65
66
- 基于以上原因, 我们将 [ 功能分支工作流] ( https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow ) , [ 交互式变基的使用方法] ( https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing ) 结合一些 [ Gitflow] ( https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow ) 中的基础功能 (比如,命名和使用一个 develop branch)一起使用 。 主要步骤如下:
66
+ 基于以上原因, 我们将 [ 功能分支工作流] ( https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow ) , [ 交互式变基的使用方法] ( https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing ) 结合一些 [ Gitflow] ( https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow ) 中的基础功能一起使用 。 主要步骤如下:
67
67
68
- ### 2.1 项目初始建立` master ` and ` develop ` 二个分支
68
+ ### 2.1 项目初始建立` master ` 和 ` release ` 二个分支
69
69
70
- - 针对一个新项目, 在 github 上创建项目的 repo,用 github 界面创建 ` develop ` 开发分支, ` clone ` 到本地后,只基于开发分支做开发 :
70
+ - 针对一个新项目, 在 github 上创建项目的 repo,同时用 github 界面创建 ` release ` 发行分支仅用于新版本发布上线。 ` clone ` 到本地后,只基于 ` master ` 分支做开发 :
71
71
72
72
``` sh
73
73
git clone < 项目地址> # clone the remote repository
74
- git checkout develop # set the develop branch as the current branch
75
74
```
76
75
77
76
### 2.2 创建功能分支做具体开发
78
77
79
- - 检出(Checkout) 一个新的功能或故障修复(feature/bug-fix)分支。同步到 Github, 随时用 ` git branch -a ` 检查当前分支状态:
78
+ - 第一步: 检出(Checkout)一个新的功能或故障修复(feature/bug-fix)分支或用 github 界面基于 ` master ` 创建功能分支。下面是命令行创建功能分支并同步到服务器。 随时用 ` git branch -a ` 检查当前分支状态。
80
79
81
80
``` sh
82
81
git checkout -b my-feature # create a new branch my-feature from the current branch
83
82
git push -u origin my-feature-branch # sync to remote server
84
83
git branch -a # display branch status
85
84
```
86
85
87
- - 在功能分枝上进行新功能的开发,提交代码并同步到远程 Git 服务器 。
86
+ - 第二步: 在功能分枝上进行新功能的开发,提交代码并随时同步到远程 Git 服务器做备份 。
88
87
89
88
``` sh
90
89
git add . # Add all local changes
@@ -96,38 +95,40 @@ git push # push to remote frequently to bakcup changes
96
95
97
96
> ` git commit -a ` 会独立启动一个编辑器用来编辑您的说明信息,这样的好处是可以专注于写这些注释说明。请参考下面关于说明信息的要求。经常同步到远程库做备份。通常在 IDE 里执行上面三个操作也可以,注意当前分支为功能分支就好。
98
97
99
- ### 2.3 合并功能分支到` develop ` 分支
98
+ ### 2.3 合并功能分支到 ` master ` 分支
100
99
101
- - 1)在准备提交合并前, 先将需要 merge 到的分支更新到最新,例如要将功能分支 merge 到 develop,那么需要更新 develop 到最新。下面的步骤建议手工运行。
100
+ 当功能开发完成时,要将所做工作变基并入 ` master ` 分支。
101
+
102
+ - 第一步:在准备提交合并前, 先将需要 ` master ` 分支更新到最新。下面的步骤建议手工运行。
102
103
103
104
``` sh
104
- git checkout develop
105
+ git checkout master
105
106
git pull
106
107
```
107
108
108
109
为什么
109
110
110
111
> 当您进行(稍后)变基操作的时候,保持更新会给您一个在您的机器上解决冲突的机会。这比(不同步更新就进行下一步的变基操作并且)发起一个与远程仓库冲突的合并请求要好。
111
112
112
- - 2) 切换至功能分支,变基 ` develop ` 分支到功能分支,并采用 ` rebase -i --autosquash ` 的交互方式
113
+ - 第二步: 切换至功能分支,把功能分支变基到 ` master ` 分支,建议采用 ` rebase -i --autosquash ` 的交互方式
113
114
114
115
``` sh
115
116
git checkout my-feature
116
- git rebase -i --autosquash develop
117
+ git rebase -i --autosquash master
117
118
```
118
119
119
120
为什么
120
121
121
- > 您可以使用 ` --autosquash ` 将所有提交压缩到单个提交。没有人会愿意(看到) ` develop ` 分支中的单个功能开发就占据如此多的提交历史。 [ 更多请阅读...] ( https://robots.thoughtbot.com/autosquashing-git-commits )
122
+ > 您可以使用 ` --autosquash ` 将所有提交压缩到单个提交。没有人会愿意(看到) ` master ` 分支中的单个功能开发就占据如此多的提交历史。 [ 更多请阅读...] ( https://robots.thoughtbot.com/autosquashing-git-commits )
122
123
123
- - 如果没有冲突请跳过此步骤,如果您有冲突, 就需要[ 解决它们] ( https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/ ) 并且继续变基操作。
124
+ - 第三步(可能需要): 如果没有冲突请跳过此步骤,如果您有冲突, 就需要[ 解决它们] ( https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/ ) 并且继续变基操作。
124
125
125
126
``` sh
126
- git add < file1> < file2> ...
127
- git rebase --continue
127
+ git add < file1> < file2> ... # 任何必要的增删改
128
+ git rebase --continue # 继续刚才的变基操作
128
129
```
129
130
130
- - 3) 推送您的功能分支到 github。变基操作会改变提交历史, 所以您必须使用 ` -f ` 强制推送到远程(功能)分支。 如果其他人与您在该分支上进行协同开发,请使用破坏性没那么强的 ` --force-with-lease ` 参数 。
131
+ - 第四步: 推送您的功能分支到 github。变基操作会改变提交历史, 所以您必须使用 ` -f ` 强制推送到远程(功能)分支。 如果其他人与您在该分支上进行协同开发,请使用破坏性没那么强的 ` --force-with-lease ` 。
131
132
132
133
``` sh
133
134
git push -f
@@ -137,29 +138,26 @@ git push -f
137
138
138
139
> 当您进行 rebase 操作时,您会改变功能分支的提交历史。这会导致 Git 拒绝正常的 ` git push ` 。那么,您只能使用 ` -f ` 或 ` --force ` 参数了。[ 更多请阅读...] ( https://developer.atlassian.com/blog/2015/04/force-with-lease/ )
139
140
140
- - 4) 提交一个合并请求(Pull Request)。Pull Request 会被负责代码审查的同事接受,合并和关闭。合并请求完成同时需要删除远程的功能分支。这些操作都利用 github 的用户界面进行。
141
+ - 第五步: 提交一个合并请求(Pull Request)。Pull Request 会被负责代码审查的同事接受,合并和关闭。合并请求完成同时需要删除远程的功能分支。这些操作都利用 github 的用户界面进行。
141
142
142
- - 5) 合并完成后,记得删除您的本地分支。
143
+ - 第六步: 合并完成后,记得删除您的本地分支。
143
144
144
145
``` sh
146
+ git checkout master
145
147
git branch -d < 分支>
146
148
```
147
149
148
150
(使用以下代码)删除所有已经不在远程仓库维护的分支。
149
151
150
152
``` sh
151
- git fetch -p && for branch in ` git branch -vv | grep ' : gone]' | awk ' {print $1}' ` ; do git branch -D $branch ; done
152
- ```
153
-
154
- 命令太长,建议在` .bash_profile ` 创建一个` alias ` :
155
-
156
- ``` sh
157
- alias syncBranch=' git fetch -p && for brach in `git branch -vv | grep ": gone]" | awk "{print $1}"`; do git branch -D $branch; done'
153
+ git checkout master
154
+ git fetch -p
155
+ git branch -D featureBranch
158
156
```
159
157
160
- ### 2.4 开发分支发布到 ` master ` 分支
158
+ ### 2.4 版本发布到 ` release ` 分支
161
159
162
- TODO.
160
+ 由程序员、运维人员和项目经理共同决定发布的时机。具体流程另外描述。
163
161
164
162
## 3 如何写好 Commit Message
165
163
0 commit comments