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