产品: "上次提的3个需求, 今天就上1个, 另外2个不用了"
开发: "我代码昨天都写完提交了, 那只能把2个需求代码删掉了. 我可是有代码洁癖的, 不能让我的项目里这么多无用代码留着"
[两小时后]
产品: "我想了一下, B功能还是要上的, 一共上2个功能"
开发: "行吧, 我再把代码拷贝回来"
[临上线]
产品: "不行, 下掉B功能, 上C功能! 快!!!"
开发: "W-- 我佛慈悲!"
[上线后]
老大: "C功能有bug, 立刻回滚"
开发: "好, 我退回到上次发版的快照"
这是日常的一天, 也是糟糕的一天, 大把的时间浪费在代码的删除和拷贝上, 而不是在创造上。
问题出在哪了?
上节我们提到, Git 每个 Commit 都有两种属性, 快照和补丁. 在上面的使用场景中, Git 只发挥出了不到一层功力, 大家关注的仅
仅是最新提交点的快照, 当然, 这个快照是极为重要的, 重要到我们的HEAD指针几乎总是在指向他, 重要到我们会把他称为最新
的master分支。
我们把关注点转移到 Git 的补丁属性上来, 你每天提交的 commit 代表着你这一天的工作成果, 那么描述怎么写?
"张三20190622工作"? 还是 "增加了A功能, B功能, C功能写了一半"
或许后者稍微好一点儿, 至少在几天时候查看 Git 提交记录时能一目了然的知道这次提交包含什么修改。
还记得git diff的输出吗? 是行级的差异。 为什么不是文件级别, 或者字符级别? 每次代码提交以天为单位真的合适吗? 当然不合
适, 每个 commit 的最佳粒度应该是相对独立的特性(feature), 比如上文提到的A, B, C三个功能。
理想情况下, A, B, C是三个独立的功能, 分别作为三次 commit。
更好的做法是什么?
还记得吗? A, B, C都是独立的补丁(patch), 那么A, B, C的次序是没有关系的, 也就是说C1, B2, A3的代码快照应该是一样的. 不
信试一下, 可以用git diff验证结果。
当要求撤掉 B 功能时, 如果可以直接删掉 B 这次提交, 那么瞬间就达到目的了. 但是, 有两点是需要考虑的 :
一般来说, 大家同时使用的分支只前进, 不后退, 即不能篡改历史;
若真的篡改了历史, 那么 B 功能的代码就从提交记录上消失了, 万一需要再次添加 B 功能, 这将是悲剧。