?!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
很多开发者仅仅只把版本控制系l当成是一堆文件的备䆾。这些历史备份除了可以让你取回某个时间点上的文g内容之外Q没有Q何其他用处。下面这些徏议可以帮你把你的版本控制pȝ从一个备份系l,变成用于沟通和文档~写的一个宝늚工具?/p>
1. 每次提交只做一个修?/strong>
如果你在一ơ提交中修复了F00-123和F00-233、重构了一个类、界面上d了一两个按钮、还有把整个目文g中的 tab ҎI格Q那么基本上没有 review F00-123 ?bugfixQ只有你自己才知道哪些修改属于那?bugfix 的一部分Q但是一周以后很可能你自己都忘了?/p>
要是一周以后你发现原来的那?bugfix D了另外一个更严重的问题那你就完蛋了,你不能用hg backout或者git revert来撤销你的修改Q因为那样会把除了那?bugfix 之外的所有修攚w撤销掉,也意味着你一周的努力白费了?/p>
上面q种问题的解军_法就是“每ơ提交只做一个修改”,对于怎么h是“一个修改”没有Q何硬性或者既定的规则Q但如果你能够用一个句子ƈ且不用用到“和”这个字来描qC所做的所有事情,那么你算是做C?/p>
分布式版本控制系l其中一个很好的功能是Q如果你的工作目录中有很多相互之间没有关联的修改Q你可以用它来帮你收拑֥你的烂摊?clean up the mess you’ve made)Q但是最好别在一开始就搞出一个烂摊子。在你开始修改代码之前,先确定你惛_什么和你想怎么做,然后再认真把xҎ在你想修改的那个点上?/p>
在没有想出怎么改进某块代码之前Q貌g太可能去修改那块代码。你发现?bug、看C一些糟p的代码、还有一些你很好奇想q一步了解的东西。无Z多么惛_做,千万别被转移了注意力。这些发现非常有价|用一个笔记本或者一?TODO 文g把他们写下来(jot them down)Q在完成当前d之前不要惛_解决那些问题?/p>
q个不仅仅是关于更好地提交。当你沉在解决某个~程问题里面的时候,你的头脑充满着关于q个问题的一堆细节,如果q个时候你跛_想一些其他问题,那么你会忘了原来那个问题的细节,再回到原来那个问题需要花一些时间。你需要减Q务切?minimize task switches)来提高你的工作效率?/p>
当然有些时候你会发现在没有解决某些其他问题之前Q你很难完成当前的Q务。这个时候最单的方式是使用hg shelve或者git stash把你当前q没有完成的修改暂存hQ把两个问题的修改分开Q提交那个被依赖的修改,再回C原来的Q务上面去?/p>
2. 每次提交要包含完整修?/strong>
如果一个修改分布到了几个提交里面,那么q个修改也是很难 review 的。通常q是因ؓ在同一旉解决太多问题D的,如果你吃不了那么多,却啃了那么多Q那么在你想保存其中的某些修改的时候,你会发现大部分的修改都是未完成的。同一旉x太多问题会导致最后需要很长时间才能够提交完整的修攏V(原文是:Focusing on one task at a time takes you a long way towards committing complete changes. 但我觉得作者的原意应该是:Focusing on too many tasks at a time takes you a long way towards committing complete changes.Q?/p>
有些修改需要花很长旉Q所以如果中间在某个点上你搞错了Q重头再来你肯定折腾不vQ所以你需要在q程中保存一些中间版本。幸好分布式版本控制pȝ都允怽保存很多中间版本但是最后只提交一ơ修改到中心版本?central repository)Q你可以提交L多次的中间版本,在最后用hg histedit或者git rebase把多ơ的中间版本合ƈ成一个修攚w?/p>
另外一U,也是我个人比较喜Ƣ的ҎQ因为它把中间版本和怹性的修改版本分开了,q种Ҏ使用 Git ?indexQ或?Mercurial Queues 中的一?patch 来保存最q一ơ正的Q没?bug 的)中间版本Q每ơ你做了新的修改你都更新q个 index/patchQ如果你犯了个错误,你就可以使用他们恢复你的工作目录了。I like to think of it as a one-slot quicksave for version control.Q译注:q句只可意会Q我不知道怎么R)
3. 写好注释Q说明你修改了什?/strong>
像“修?Fixes)”、“提?Commit)”这L提交信息没包含Q何有用的信息。如果别人想看看版本历史Q像q样的提交信息只会g们去看完所有的代码修改Q看代码是很Ҏ费力的。写q样一个简短但表达不清晰的提交信息Q可能是省了你一分钟旉Q但是却费了其他h几个时?/p>
一个好的提交信息可以让看的人清楚代码的哪一部分被修改了Q是怎么被修改的Q他们也不需要去看你的代码:
SomeClass: use bleh instead of xyzzy in someMethod (fixes FOO-123)
4. 注释说明Z么做q个修改
假设每次修改代码都有一个很好的理由/原因Q但如果q个理由/原因被没有记录下来,那么整个代码?codebase)面临以下风险:
其他开发者不明白Z么原代码是那样写的。当他们修改代码的时候,他们可能会引入一些原作者已l发现或者避免的问题?/p>
其他开发者认为原代码那样写肯定是有(好的Q原因的Q所以最好别动它。他们把q些代码看成是一个黑盒,然后加各U复杂的 workaroundQ避免修改原代码。最后导致这个代码库变得臃肿Q代码变得难以看懂?/p>
如果你有_的理由有必要破坏一个项目的规范或者约定,那一定要把这个理׃为注释写在你的代码里面:
- xyzzy (bars); + // Our bars are already sorted, so bleh is much faster than xyzzy + bleh (bars);
如果你的代码遵守了规范,q且你的代码没有什么微?subtleties)的点需要注意,那就没有必要把你的文档注释写在代码里面。但仍然有必要让人知道ؓ什么新代码优于旧代码(其是当C码引入了一个新问题Q,所以还是要把原因写在提交信息里面的Q?/p>
SomeClass: Don't flush caches in someMethod The caches are flushed automatically at the end of each request.
如果一个修改解决了一个已知问题,保在提交信息里面带?ticket Pbug q踪pȝ中的 ticketQ,以便其他开发者在看版本历史的时候能够清楚地知道是在什么情况下做出的这个修攏V?/p>
5. 不要提交被注释掉的代?/strong>
我没有办法理解提交被注释掉的代码背后的理Z据,我假设这是ؓ了保存旧代码Q以防新代码不能正常工作Q但q种做法很莫名其妙,最开始我们用版本控制系l不是Z保存旧版本吗Q!
Z么要注释掉这些代码?q些代码能运行吗Q会正常q行吗?曾正常运行过吗?注释代码是我们应该支持还是摒弃的呢?被注释掉的代码毫无用处,因ؓ每当开发者读到这些被注释的代码,M冒出一些没有答案的问题Q它只会h开发者视听,让开发者分心而无法更好专注于有用的代码?/p>