在团队开发过程中, 不同的开发同学习惯使用不同的操作系统和开发工具, 再加上每个开发人员对于换行符/缩进等等有各自的偏好, 这些问题都可能导致代码库中的代码格式混乱.
混乱的代码库和开发人员偏好可能导致很多潜在的问题:
cherry-pick
, revert
等应对突发情况的灵活手段.
针对上述问题, 虽然各个语言都有一些静态代码检查工具 (如 Java 的 JLint, JavaScript 的 ESLint 等), 并且检查的逻辑也更加严格和复杂. 但这些工具大都是为专门的语言设计, 对于种类繁多的配置文件就无能为力了.
本文将介绍如何通过Git的内置机制, 来尽量避免团队协作过程中可能出现的编码格式混乱的问题.
使用Git的内置机制的好处是: 第一, 配置容易, 相比于 xxlint 之类的工具, 它在团队中推广成本更低; 第二, 编程语言无关, 任何文本文件都能被覆盖到.
通过利用Git的内置机制, 只需要团队成员进行简单的本地配置, 就能保证团队能产出干净的代码仓库和提交历史, 同时也为 Code Review 打下基础.
git config --global core.eol lf
git config --global core.autocrlf input
git config --global core.safecrlf false
以上三项设置使得我们可以保证代码仓库中的文本文件统一使用LF作为换行符, 而不会因为不同的开发者使用不同的操作系统而使得代码被频繁地大量改变. 这项设置降低了文本diff的噪音, 保证了代码review的效率.
core.eol
设置决定了具有 text
属性的文件的默认换行符. (注意当 core.autocrlf
被设置后 core.eol
可能被强制调整)
core.autocrlf
这个配置决定了git如何对待文本文件中的crlf
换行符. 设置为 input
使git在commit文本文件的时候, 自动将文本中的换行符换为LF (unix格式), 而在checkout的时候不做转换. 而当设置为 true
时, git在commit文本文件的时候, 自动将文本中的换行符换为LF (unix格式), 而在checkout的时候转换换行符为系统默认方式.
将 core.autocrlf
设置为 input
或者 true
都能保证自己提交到库中的文本文件以LR作为换行符, 但是我推荐使用前者 (即 autocrlf
为 input
), 因为在使用后者的情况下, 如若团队中有其他成员将错误的换行符提交到了库中, 由于你在checkout代码的时候换行符被统一做了转换, 所以你可能很难发现问题所在. 而不论工作区的文本采用哪种换行符, 大部分现代的代码编辑器都能正确处理, 所以不必让git做checkout时的转换.
core.safecrlf
有 true
, warn
, false
三个选项, 分别表示 "不允许替换换行符", "允许替换换行符且打印警告", "替换换行符且不打印警告".
git config --global core.whitespace trailing-space,space-before-tab,-cr-at-eol,indent-with-non-tab,-tab-in-indent,tabwidth=4
这个配置将开启若干项检查:
trailing-space
: 提示尾空白(包括 blank-at-eol
行尾空白 和 blank-at-eof
文件末尾空白).space-before-tab
: 提示Tab之前的空格.-cr-at-eol
: 提示CR换行. (cr-at-eol
选项使得Git忽略对换行中出现CR的检查, 在该项前面加 -
表示disable这项)indent-with-non-tab
: 提示非Tab的缩进. 当团队约定使用Tab缩进时, 可以开启该项, 这样 Git 在发现非Tab缩进时将高亮它 (注意: 这时候 Git 只会高亮 tabwidth 个以上空格的缩进).tab-in-indent
: 提示Tab缩进. 当团队约定使用空格缩进时, 可以开启该项, 这样 Git 在发现Tab缩进时将高亮它. 它和 indent-with-non-tab
是互斥的选项, 两者只能开启其中之一.tabwidth=4
: 设置Tab和空格的等价关系: 1个Tab = 4个空格. 它在检查和修复缩进错误时会被用到.
当开启这些检查后, 用户在本地使用 git diff
等命令时 Git 会将无意义的空白高亮, 让用户能意识到这些非法空白的存在, 这可以帮助确保仓库中不会有大量的冗余空白, 使得 Merge Request 中的 diff 结果更加干净.
需要注意的是, 这些检查项只是给你警告, 而不会自动帮你修复. 如果需要Git帮助修复这些问题的话, 可以通过设置 git hook做到自动修复, 也可以在本地提交后通过 git rebase --whitespace=fix
主动修复.
git config --global merge.ff only
这个配置使得在 merge
或 pull
的时候默认只支持fast-forward合并, 若非fast-forward (存在分叉) 则必须手动指定 --no-ff
参数才允许合并. 这样的限制确保了所有的因为合并行为而产生的commit都是用户有意识地确认过的, 而不会因为随意 pull
代码而产生大量无意识的提交记录, 并且也鼓励了用户使用 git pull --rebase
命令来整理提交记录. 总之这个设置对于团队仓库获得清晰的提交记录意义重大.
git config --global tag.sort version:refname
这个配置使得tag被当做版本号排序, 即: 使得 v2.10
会排在 v2.9
后面. 这是一个大家值得拥有的方便配置.
git config --global log.date iso
这个配置使得日期默认以 2017-06-01 16:38:39 +0800
的格式显示, 而不是 Thu Jun 1 16:38:39 2017 +0800
的格式. 对我这种英文月份背不全的人来说, 这个设置方便了不止一点点...
git config --global core.eol lf
git config --global core.autocrlf input
git config --global core.safecrlf false
git config --global core.whitespace trailing-space,space-before-tab,-cr-at-eol
git config --global merge.ff only
git config --global tag.sort version:refname
git config --global log.date iso
如果你的团队对于缩进方式有明确的约定, 你还可以使用下面这些更为严格的空白检查选项:
使用Tab缩进, 并在修复时将4空格替换为Tab:
git config --global core.whitespace trailing-space,space-before-tab,-cr-at-eol,indent-with-non-tab,-tab-in-indent,tabwidth=4
使用空格缩进, 并在修复时将Tab替换为4空格:
git config --global core.whitespace trailing-space,space-before-tab,-cr-at-eol,-indent-with-non-tab,tab-in-indent,tabwidth=4
执行以上命令可修改git的全局配置, 若希望只修改指定项目的git配置, 可以将以上命令中的 --global
参数去掉, 并 cd
到该项目根目录下执行以上命令.
要知道通过 git config
命令设置的配置项只会跟着用户走 (或者更准确地说, 是跟着用户的磁盘走), 而不会跟着项目走, 它们无法影响到参与同一个项目的其它用户. 用或者不用 --global
参数的区别仅仅是, 用 --global
会影响到一个用户的所有项目的默认设置, 而不用 --global
则是影响一个用户对某个具体项目的设置. 因此, 对于一些项目自身的内禀属性, 还是通过 .gitattributes
和 .gitignore
等会被Git仓库跟踪的配置文件来设置更为稳妥.
更详细的设置说明可以参考相关文档
本文来自网易实践者社区,经作者罗宸权发布