一、user.name 配置
Git 的 user.name
配置一定要使用自己的中文名称。命令行操作方式如下:
git config --global user.name "自己的中文名字"
二、commit 提交规范
每个提交要保证适当的颗粒度、相关性和独立性。
- 以一个小功能、小改进或一个 bug fix 为单位
- 对应的
unit test
程序在同一个commit
- 无相关的修改不在同一个
commit
- 语法错误的半成品程序不能
commit
三、Git 操作流程
团队开发中,遵循一个合理、清晰的 Git 使用流程,是非常重要的。否则,每个人都提交一堆杂乱无章的 commit,项目很快就会变得难以协调和维护。
第 1 步:新建分支
首先,每次开发新功能或修复 Bug,都应该新建一个单独的分支。
# 获取主干最新代码
$ git checkout develop
$ git pull --rebase
# 新建一个开发分支 branch-name
$ git checkout -b branch-name develop
注意:
branch-name
的命名规如下:
- 功能开发,
branch-name
应为feat-n
。feat
是 feature(功能)的前四个字母,n 是一个数值对应于 Redmine 上功能编号,中间用横线连接。例如:feat-30,如下图所示: - Bug 修复,
branch-name
应为 fix-n。fix 是修复的意思,n 是一个数值对应于 Redmine 上 Bug 编号,中间用横线连接。
第 2 步:提交分支 commit
分支修改后,就可以提交 commit 了。
$ git add .
$ git status
$ git commit --verbose
git add 命令的 all 参数,表示保存所有变化(包括新建、修改和删除)。从 Git 2.0 开始,all 是 git add
的默认参数,所以也可以用git add .
代替。
git status
命令,用来查看发生变动的文件。
git commit
命令的 verbose
参数,会列出 diff 的结果。
第 3 步:撰写提交信息
Git commit message
的撰写规范,请参考:[[kmc:Commit message 和 Change log 编写规范]]
第 4 步:与主干同步
分支的开发过程中,要经常与主干保持同步。
$ git checkout develop
$ git pull --rebase
第 5 步:合并 commit
分支开发完成后,很可能有一堆 commit,但是合并到主干的时候,往往希望只有一个(或最多两三个)commit,这样不仅清晰,也容易管理。
那么,怎样才能将多个 commit 合并呢?这就要用到 git rebase 命令。
$ git checkout branch-name
$ git rebase -i HEAD~n
git rebase
命令的 i 参数表示互动(interactive),这时 git 会打开一个互动界面,进行下一步操作。n 代表变基操作的提交数量。
下面采用 Tute Costa 的例子,来解释怎么合并 commit。
pick 07c5abd Introduce OpenPGP and teach basic usage
pick de9b1eb Fix PostChecker::Post#urls
pick 3e7ee36 Hey kids, stop all the highlighting
pick fa20af3 git interactive rebase, squash, amend
# Rebase 8db7e8b..fa20af3 onto 8db7e8b
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
上面的互动界面,先列出当前分支最新的 4 个 commit(越下面越新)。每个 commit 前面有一个操作命令,默认是 pick,表示该行 commit 被选中,要进行 rebase 操作。
4 个 commit 的下面是一大堆注释,列出可以使用的命令。
- pick:正常选中
- reword:选中,并且修改提交信息;
- edit:选中,rebase 时会暂停,允许你修改这个 commit
- squash:选中,会将当前 commit 与上一个 commit 合并
- fixup:与 squash 相同,但不会保存当前 commit 的提交信息
- exec:执行其他 shell 命令
上面这 6 个命令当中,squash 和 fixup 可以用来合并 commit。先把需要合并的 commit 前面的动词,改成 squash(或者 s)。
pick 07c5abd Introduce OpenPGP and teach basic usage
s de9b1eb Fix PostChecker::Post#urls
s 3e7ee36 Hey kids, stop all the highlighting
pick fa20af3 git interactive rebase, squash, amend
这样一改,执行后,当前分支只会剩下两个 commit。第二行和第三行的 commit,都会合并到第一行的 commit。提交信息会同时包含,这三个 commit 的提交信息。
# This is a combination of 3 commits.
# The first commit's message is:
Introduce OpenPGP and teach basic usage
# This is the 2nd commit message:
Fix PostChecker::Post#urls
# This is the 3rd commit message:
Hey kids, stop all the highlighting
如果将第三行的 squash 命令改成 fixup 命令。
pick 07c5abd Introduce OpenPGP and teach basic usage
s de9b1eb Fix PostChecker::Post#urls
f 3e7ee36 Hey kids, stop all the highlighting
pick fa20af3 git interactive rebase, squash, amend
运行结果相同,还是会生成两个 commit,第二行和第三行的 commit,都合并到第一行的 commit。但是,新的提交信息里面,第三行 commit 的提交信息,会被注释掉。
# This is a combination of 3 commits.
# The first commit's message is:
Introduce OpenPGP and teach basic usage
# This is the 2nd commit message:
Fix PostChecker::Post#urls
# This is the 3rd commit message:
# Hey kids, stop all the highlighting
第 6 步:推送到远程仓库
合并 commit 后,就可以推送当前分支到远程仓库了。
$ git push --force origin branch-name
git push 命令要加上 force 参数,因为 rebase 以后,分支历史改变了,跟远程分支不一定兼容,有可能要强行推送。
第 7 步:发出 Pull Request
提交到远程仓库以后,就可以发出 Pull Request 将分支合并到 develop 分支,发起 Pull Ruquest 之后,可以做两件事情:Bug 回归测试和 Code Review。
- Bug 回归测试。这是可选的,当分支是 Bug 修复分支(fix-m)时,需要做回归测试,回归测试通过,才能 Merge
- 但是,当分支是功能开发分支(feat-n)时,不需要做 Bug 回归测试,但是开发人员需要自己保证代码是经过测试的
- Code Review。不管分支是 Bug 修复分支还是功能开发分支,都需要利用开发规范对提交的代码进行静态检查。
- 在 Pull Request 页面,项目组的其他开发人员对程序代码和 Git commit 注释,进行检查和审核
- 如果有问题,需要在相应分支上做修改代码或者 Git 变基操作
- 注意,在合并代码之前,开发人员如果收到 develop 分支上其他分支的 Merge 事件,应该主动在本地仓库的分支上执行如下命令:
git rebase develop
git push -f branch-name
第 8 步:合并 Pull Request
一旦检查完毕,没有问题,则进行合并操作。注意,合并操作,不应该由提交代码的开发人员本人进行合并,而是应该由其他人进行合并。而且,在合并之前,应该在 Pull Request 备注文字,例如:本次提交的代码,经检查没有问题,可以合并。
四、如何提高 PR 流程的效率
PR(Pull Request)的意义重大,因为有了 PR 这个缓冲,代码在合并到主干之前可以进行 Code Review,有了 Code Review,开发人员的技术能力就有了提升的空间。否则,不管代码是否规范,直接提交到版本仓库中,没有任何回旋的余地。有了 PR,也可以有效的减少冲突代码的互相覆盖。虽然 PR 有诸多好处,但是很多开发人员的了解 PR 的第一反应就是降低了开发流程的效率。其实 PR 没有真正降低效率,想象一下,如果没有 PR,开发人员提交代码导致了代码的覆盖和丢失,寻找丢失和覆盖的代码是不是效率更低呢?至于如何开展 PR,见上面的 Git 流程介绍。下面谈几点提高 PR 流程效率的技巧:
- 尽早解决冲突
当发出 PR 后,GitHub 会立刻检查当前分支和长期分支是否有代码冲突(如下图所示)。一旦有冲突发生,是无法完成代码合并的。这个冲突状态是 GitHub 很快能够提示出来的,所以,开发人员在发起 PR 之后,应该在 PR 的页面上等待页面提示是否有冲突的信息出现,如果发现有代码冲突,应该第一时间去解决代码冲突。在确保 PR 中没有冲突的情况下,再继续 PR 的后续流程。
- 主动要求 Code Review
当发出 PR 后,一般情况下,项目所有参与者都会收到邮件提醒,但是邮件提醒是有时间间隔的。所以,如果发出 PR 后,可以主动把 PR 页面的 URL 地址,通过企业微信或者 QQ 发送给项目组成员。或者直接发送给高杨、王树贤或者王顶,要求 Code Review。当然,如果 PR 是 bug 修复,应该同时把 PR 页面的 URL 链接发送给测试人员,要求测试人员进行测试,测试通过后,测试人员应该在 PR 页面上备注测试是否通过的信息。测试和 Code Review 可以同时开展,这样可以提高流程的效率。
总结一下:在企业的任何工作流程中,提高效率的关键要点无非三个:一是减少流程中间的等待时间,二是尽量提高任务并行的程度,减少任务串行的程度,三是尽量减少不必要的重复或者任务。