Practical Git
TL;DR 一些自以为是的 Git 经验和实践建议,有感而发,慎重参考。
Merge vs Rebase
建议:Merge into main, but rebase feature branches
不建议:自己执行任何一句 git merge 命令,(起码我想不到某一个场景是必须这么做的)。让你的 CI 工具来做这件事(把特性分支最终合入主干)。
如果你需要解决多个特性之间的冲突,梳理清楚其先后顺序,让后来的特性分支 rebase 到前面的特性分支上。或者更好的,提取出稳定的公共的部分作为共同前缀。 如果冲突多到你难以处理 rebase 命令,且不是因为你自己的 commit 历史过于复杂上,那必定是需求拆解的问题。
最终在主干上的所有的 merge 节点的集合就是你二分查找问题的截点。
Commit Message
如果你的组织有规范,遵守它。不过如果规范形式主义远大于实际意义,不妨试试那个神奇的 ✨ 按钮来减少心智负担。
有种我赞同的说法是:如果你的项目里所有的 commit message 都有着简短的总结和无比详细的描述,那通常说明这里的 CI 和 Review 流程太差劲了。
开发过程中不是所有 commit 都需要有意义,你可以在第一个 commit 里写下特性包含的内容和方向。完成一点就可以提交保存下来,甚至可以直接 --allow-empty
来提交一个空的 commit 梳理自己的思路。后续 commit 随时提交,写个 .
就行。当你差不多满意了,rebase -i 全部 fixup 到第一个就行,优美一点还可以 amend date 让时间戳更正确。
个人可能是有些奇妙的羞耻感,对于一些“愚蠢”的中间错误,不想留下痕迹给后人看,所以我会倾向于继续合并掉这些中间过程。也可以合理地解释为 Git 历史是用来回溯的,冗余甚至错误的信息只会增加负面影响,所以没有必要保留。
.gitignoreinclude
看到的一篇文章讲如何把你的 .gitignore 文件用成只允许特定文件的白名单,其他的都不允许提交。之前知道这种 !
的用法,但从来没想过要这么做。
感觉是有趣的一个实践,保持了我喜欢的“默认拒绝”,“保证知道你在做什么的”特点。
还能顺便解决你没用过的各种 IDE 的配置文件、不同操作系统平台的特别文件(点名批评 .DS_Store)被其它人失误提交的问题。
具体执行大概可以这么写:
*
!.gitignore
# whitelist `src` directories and their children, regardless of place
!src/
!src/**/
!src/**/*.rs
!Cargo.{toml,lock}
!/docs/
!/docs/*.md
tradeoff 是你需要手动维护这个白名单,添加的任何新模块都要注明一下。
Looking forward
受限于环境,自己还没享受到但是期望的流程:
- 所有改动是小且明确的,且并不是所有变动都需要完整的真实环境验证才能合入主干。很多时候只需要 CI 跑通就行了。
- CI 和 CI 后操作是无需手动干预的,如设置好检视OK + CI 全部通过以后可自动执行合入操作。
- 成熟的团队,代码检视工作甚至都可以是后置的,不阻塞合入。检视意见完全可以在后续用新的 patch 继续处理。
在开发之后,CI、检视、合入、发布这些步骤都不应该是完全同步阻塞的。