网页排版清单

译自:http://www.merttol.com/articles/web/checklist-for-better-web-typography.html

找到一个简单可行的网页排版清单,个人感觉可以当入门级参考来使用。这个网站同时还有一个完整的设计清单,不只是排版相关的。


排版可以影响到读者是否阅读这里的内容,也潜移默化的让他们注意到你的网站。选择适当的字体并控制它们的展现形式是你传递信息的关键。

下面的清单用来归纳出一些要点,帮助你在网站上线之前确认一下是不是所有该做的事情都做到了。

  • 布局
  • 字体和格式
  • 内容
  • 艺术字

关于布局,你是否:

  1. 把内容通过大标题、小段落、列表符号、侧边栏、缩紧或引用将其分开?
  2. 通过分栏将较宽的页面将行宽限制在 350~550 像素内?
  3. 加重加大显示首字母/首行以改进较长文本的可读性并让整个页面的配色更明亮?
  4. 增加字母或单词直接的空隙以示强调?
  5. 首行缩紧或双倍段落间距,但不要两者兼有?
  6. 避免把紧跟在标题后面的段落缩进?
  7. 在标题之前使用双倍段落间距但是在标题和其引出的内容之间使用单倍段落间距?

关于字体和格式,你是否:

  1. 为正文文案使用无修饰的、针对屏幕优化过的字体且使用清晰易读的大小?
  2. 为长文本适度使用更松散的首字母/首行,或减轻页面的密度,以示强调?
  3. 使用更宽的字符或单词空隙,以示强调?
  4. 将正文左端对齐,右端参差不齐
  5. 通过对比性的元素,比如不同的字体、字号、字重、颜色、格式、结构、加粗、斜体、相反的文本颜色和背景色、全大写、纹理、方向、节奏、距离和修饰来强调特殊的文本区域?
  6. 克制的使用这些列出的元素?
  7. 通过 CSS 自动设置特殊的大小写规则 (全大写、全小写、标题情形)?
  8. 在正文中避免使用全大写?
  9. 只在链接上使用下划线?
  10. 灰度模式下测试你的网站以确保前景色和背景色有足够的对比度?
  11. 如果在暗色背景中使用亮色文字,则考虑将文本加粗或选择一款本身字形较粗的字体?
  12. 避免删除线,除非你想展示的是该文档之前编辑过的版本?
  13. 考虑使用 CSS 来设置首字符或首行文本的样式?

关于内容,你是否:

  1. 检查拼写、语法和句式?
  2. 少用一些感叹号
  3. 指定合适的排版字符,包括短破折号长破折号成对的引号、真正的省略号以及大小写数字 (upper and lowercase numerals 应该指的是罗马数字 I II III IV V VI VII VIII IX X……)?

关于艺术字,你是否:

  1. 确保只在绝对必要的时候使用艺术字,避免过高的下载量?
  2. 选择合适的修饰抗锯齿字间距
  3. 为较小的文字选择有针对性设计的字体并关掉抗锯齿

最后这里还有另外一份 “设计清单”,记得看看。

为什么我不会无偿加班且你也不应该

译自:http://thecodist.com/article/whyidon39tdounpaidovertimeandneithershould_you

原文写于 2012 年,至今已经有一段时间了,前段时间这篇文章又被大家翻出来热烈讨论,看过之后有些感触,所以翻译了一下


我是一个在美国待了 30 年的程序员,我有过一周工作超过 40 小时的经历,这在行业里面并不常见,但是我很难因此而得到更多的薪水。

总之,我现在发现整个做法很恶心

我并不是针对自营或创业等多干活儿就能得到更多回报的情况。我曾经在 80 年代中期到 90 年代开过两个小的软件公司,并且工作时间也很长,但是我们会共享全部的成果,而第二家公司我们在合同里就定好了多劳多得的规矩。当然这不是我们今天讨论的重点。

如果我为一家大公司工作并且谈好了薪水,那我的预期就是我在标准的时间内,即公认的 (至少在美国) 一天 8 小时一周 5 天,尽我所能完成工作。如果他们希望我每周工作 70 个小时或有些主管期望团队每天都来上班,现在的我是会拒绝的。为什么呢?

当我们决定工作赚钱的时候,我们假定工作的主要原因是为了换取我们生活所需的开销。雇员的预期是他们会获得等价于这笔薪水的产出。但问题在于,雇主概念中的价值经常和雇员的不一样,尤其在美国和亚洲。许多公司期望薪水是固定的,但是他们创造这些价值需要完成的工作是不确定的。雇主觉得只要提高对雇员的预期和要求,就能够获得更大的回报,这样他们就可以通过为每份薪水延长工作时间来降低实质的劳动成本。

这对于雇员来说意味着什么?如果你同意了,那么你实际上就认同了自己的工作更廉价。甚至这种工作其实就是无偿的。那么作为雇员你在这样的无偿工作中收获了什么呢?在绝大多数雇主面前,你什么也没有得到。如果你是一个主管,也许会得到晋升,但是作为程序员你职业发展的道路不只是做管理这一条。如果你连续几个月每周编码超过 80 个小时,通常情况下得到的回报和一周努力工作 40 小时差不多。

在一些行业里,比如 AAA 游戏工作室,准备发布大型游戏这样的关键时刻的经历都是非常痛苦的。而你看了很多人们玩命工作然后发布没多久就下岗了的故事。当然你是可以选择休息的,但是付出的代价是多少?收益又是多少?

现在想象一下你自己是一个供应商 (我现在就是)。如果你要求在协议之上做更多的工作,那么公司付钱,供应商付出劳动。也许不会有更高的回报但不会比正常情况少。现在你是在为工作获取应有的回报。但奇怪之处在于,显然公司更倾向于根据时间付钱给你而不是你的实际产出,所以他们有的时候不会允许供应商加班。那他们为什么简单的要求雇员无偿工作或自告奋勇呢?

美国工人一般都有 10 天左右的年休假,有的时候还额外有几天病假;但是全职的美国工人评价一年只休息 5~7 天。在世界上很多地方,尤其是欧洲,政府授权 20~30 天年假,人们基本上都会把这些假期用掉。在很多国家加班并不普遍,无偿加班是极少的,甚至是非法的。人们配得上工作之外的生活,对于他们来说,只为雇主埋头工作是极其愚蠢的。而我们在美国 (以及亚洲很多地方) 很少这么思考问题。

我曾经有一个朋友,他的老板希望她的黑莓手机保持 24x7 待命状态。一年以后她拒绝并辞职了。她的老板为此大为恼火。而在那段时间她没有获得任何多余的回报。那我们为什么还这么做呢?

在欧美之间有一个很大的不同,美国的健康保险通常是和你的雇主绑定的,几乎没有其他地方给你实质的保障。如果你失业了,那么你得在有限的时间里支付一大笔 (COBRA) 费用,即便你找到了一份新工作,你的健康保险在 6 个月内也没法生效。所以对失业的恐惧感以及健康保险会让你更倾向于接受更长的无偿工作时间。感觉这个系统设计之初就想阻止你跳来跳去 (尤其是你成家之后)。在欧洲你的健康保险不会和雇主做任何绑定。如果公司想留住一个有价值的员工,他们就得采取一些积极的措施把你住。很多欧洲国家 (和欧元区) 你很难期待或要求别人无偿加班。

另外一个无偿加班的副作用是更少的人被雇佣。如果你长期让你的雇员每周工作 60~80 小时,你就不需要雇佣更多的人。但是对于雇员来说他们收获了什么呢?基本是没有什么收获的。

我想说的重点是,如果你付钱给我,那么我为你好好工作 40 小时,如果其他人愿意工作 60 或 80 小时,他们就更有价值而我就贬值了?我就应该由于没有把人生的全部都放在工作上而被解雇?那些愿意工作两倍时间的人就真的交付了两倍于我交付的价值吗?你可以反驳如果公司是根据工作时间给员工回报的,那么工作 80 小时的人就得到两倍回报,但这只是从雇主的角度来看。而雇员创造了更多的价值 (为公司带来了更多的收入) 但是没有得到任何更多的回报。当然你可以无视我,找到更多这样的公司,但是我对这种现代的“奴隶制”并不感冒

工作不能也不应该是一个人的生活的全部,这绝对是欧洲式的思维。生活对我来说也意味着更多。然而在美国有一种非常商业化的观点,就是如果你根据工作时间付钱,那么公司就不会成功;如果人们每年要休假 20 天,那么他们就会失败;一个雇员工作之外的生活一文不值。

我从 Steve Jobs 听到的一个有意思的故事是,在 iPhone 装备的几周前 Steve 要求他们把塑料屏幕换成玻璃的,所以他们通知中国的工厂,那边立刻把上千名工人叫起来,每人发一块饼干一杯茶水,让他们每天连续工作 12 小时,直到 iPhone 装配好。真是一个神奇的故事,但同时也是一个悲伤的故事。他们如此轻易的放弃了生活 (我相信他们还是根据工作时间得到了报酬) 甚至乐在其中,就为了有份工作。而且我从雇主这里听到用这个故事来激励大家做相同的事情——“如果你每周不工作 80 个小时,那么在中国某些人就会顶替你的工作”。而企业会通过这些引起笑声的国家取得成功。

经济是一门复杂的“科学”,我不想为此争辩太多。但是从一个个人工作者的角度看,就是一份付出一分回报。我有技能,公司有需求,我能作为一个有价值的工作者,但是这里是有度的。我不能对你或你的处境说什么,但是对我来说我的工作能力或工作期待是一个有限的范围。可能这是我的德国人的遗传,可能是因为我曾经在我的小公司每周工作 80 个小时的结果,可能我变老了也变聪明了,但是我更愿意享受工作和生活之间的平衡。

当我在 General Dynamics 的第一份工作时,我认识一位年轻的经理,他每周七天连续工作并且每天工作很长时间。有天在一个会上他突然猝死了。你说他没日没夜的工作最后得到了什么呢?

不为别人,也不为我自己。我努力工作,但到点该回家就会回家。你也应该这样。

寄语应届生:走出校园的几个人生转变

最近收到个邀请,有机会和大学生的在线互动交流,体裁不限。我选了上面这个题目,整理了一些心得感想,虽然活动很快就结束了,但是这些想法我打算还是以文字形式备忘一下。如果能给更多人帮助或参考,我会倍感欣慰。

目标的转变

作为学生,毫无疑问是以学业为重。在校园里,大家不出意外都会把学习定为最大的目标,围着功课转。但是工作之后,你可能面对很多事情要处理,怎么有所成就?怎么赚钱?怎么照顾好自己?怎么照顾好家庭……除了目标本身不同之外,我觉得更大的不一样在于,在相当长且连续的学生生涯中,我们没有太多选择的余地和必要,即便是有什么目标,也基本上是被动接受或被灌输的。但是走出校园之后,你面对的是一个无比自由开放的社会。这个时候你需要的不是意见,而是主见。甚至你是否做好了准备,有了足够的本事从事一项工作,还是继续学习深造修炼自我,直到自己准备好为止再工作?这也需要你的主见 (并为这个主见承担相应的后果,某种角度上)。最终很多选择是开放的,权衡的,遵从自己内心的结果。

还有一点我想说的是,因为你拥有了新的目标,而且不再会有人逼着你学习,从外部给你学习上的压力,所以客观上学习的环境也没有那么好那么纯粹了,学习这件事情会逐渐变得让你渴望、珍惜、喜欢。希望你还没有因为繁重的学业对新事物新知识,尤其是表面上枯燥但实际上对你有很多帮助的东西,失去动力。我们在校园里更多的是学习知识,然后推导这些知识可以用在什么地方;走出校园之后更多的需要思考,我遇到一个问题想解决它,究竟有多少知识哪些知识可以为我所用?也许在未来的某一天你会突然觉得,当时在校园里,学习环境那么好,怎么没有多看两本书,多做些训练。所以最好不要丢下自己看书学习的习惯,给自己定个长期的学习计划,有空就多看两本书。

学会社交

坦白地讲我觉得这在校园里并不是必备的技能。但是走出校园之后,它非常非常重要。这也是为什么几乎所有的公司都会给员工做沟通培训 (尽管那并不一定管用)。社交并不只是沟通而已,也不只是表达,更是聆听,是待人接物的每一个细节。我发现很多人在工作中,最简单的两件事情做不好,也不知道该怎么做,那就是:1 如何写邮件、2 如何开会。这表面上是职场礼数的范畴,也有很多文章介绍这些职场礼数,看上去就是个知识点罢了。但实际上一个人在理解和实践它的背后,反映的是修养,甚至是教养。这不是一两篇文章能够教会你的,是你平时为人处事方式的积累和感悟。

另外社交能力的重要性不止体现在工作中,体现在你步入社会之后可能会面对的各种场合的各种人,比如和同事下班之后一起组织些活动放松消遣一下,和老乡或老同学叙叙旧——这些也都是我刚毕业的时候经常会做的事情。但是这里我认为更重要的场景是:学会如何跟陌生人打交道,如何更主动的和陌生人交流,和这个社会交流。从最简单的跟陌生人问路、跟陌生的房东租房子、甚至搭讪对吧 ^_^,到跟不同性格的服务员、乘务员、售票员、公交车司机、出租车司机沟通或寻求帮助,再到你如何主动但又不会让对方和周围人尴尬的帮助别人,包括你是否会本能的路见不平挺身而出……抱歉这可能有点超出社交这个话题了。但这些都是有关联的不是吗?每个人在这个社会中都是一个独立的个体,但又是相互依赖相互依靠的一个集体社会。想真正融入这个社会,我觉得这些都是必须的。

最后,关于社交,还有一点很重要,就是在你刚刚加入一个公司或团队的时候,你周围的人一开始对你来说都是陌生人。这个社会上可能有很多适合你的机会,但它们不会主动找到你头上,这个时候需要你学会跟陌生人打交道。好的社交能力会让你的人生更有安全感,对自己办好一件事更有信心。和别人交流同样是一个完善自我认知的过程,尝试接受更多不同的观点,发现并理解不同的看问题的角度,有助于更认清自己,避免自以为是 (相信我,这种事情别人帮不上忙的,只能你自己领悟)。

个人发展

我觉得找工作这件事情,更多的要从兴趣出发,而不是所谓的“前途”。我逐渐越来越认同和相信一句老话:“三百六十行,行行出状元”。首先,如果对这件事情没有兴趣,你很难“用心”做好它,这样的状态也不是长久的;第二,我们已经看得见摸得着的“前途”和“机会”,往往已经不是什么好机会了,尤其是如今互联网时代事情变化发展这么快。而且那些真正抓住机会的人往往都是在完全没人看好的时候就开始全身心的投入在这个行业或方向上,才能在“机会”来临的时候抓住它,我不觉得这些人只是更厉害的“投机主义者”,如果没有兴趣在背后趋势着这些人,他们又是怎样才能在枯燥 (往往还伴随着高风险和不确定性) 的领域里这么坚定的做到今天呢?所以我的个人建议是,找工作,就完全追随自己的兴趣和内心就好了,不要想太多“这个行业比较赚钱比较有前途”之类的——它最多是你的一个参考项。找到自己的兴趣所在,相信它,相信自己,保持专注,一定有最好的回报,剩下的东西交给运(时)气(间)就好了。

再有就是要相信专业的力量,对学问保有“敬畏之心”。这里的学问不只是纯职业技术,也包括做事方式方法等等一切社科类的研究。如果一个行业的专业性丢掉了,整个行业也就被毁掉了,最后大家会一起丢掉工作,一起失败。

这种东西我觉得跟很多已经被一份工作或长期不良型的环境所固化思想的“老家伙”们讲已经不一定有意义和效果了。但是对于打算或刚刚从校园步入社会,有理想,有抱负,承载着社会的未来的大学生们来说,我希望有机会在这方面多呼吁一下。尊重和相信专业的力量,耐得住性子,不要被一时的挫折、不走运或委屈左右,多多磨练自己,你一定不会后悔。

So Are You Ready?

:)

如果管理是唯一可走的路,那就完蛋了

译自:https://moz.com/rand/if-management-is-the-only-way-up-were-all-fd/

注:作者 Rand 是 Moz 的 CEO,文中反复出现两个词:IC (Individual Contributor) 和 PW (People Wrangler),分别翻译成了一线员工和经理人。


Geraldine 很喜欢她曾经在 Cranium 的工作 (西雅图的桌游初创公司,在 Hasbro 收购他们并裁员之前)。她为桌游撰写问题,并为包装盒和营销材料撰写文案。她很擅长这个。但是发生了一些奇怪的事情——他们想让她晋升。我记得她晚上回家后非常的苦恼。她不想让人们向她汇报。她不想在团队中拥有更大的责任。她只想写写东西。

这很奇怪。当我们审视一家公司的结构时,很容易发现团队需要很多高质量的一线员工 (IC) 以及少数高质量的经理人。然而我们的公司文化和这个世界的“模式”已经让我觉得除非你要带人,否则你的影响力、薪水、利益、职位和自我价值都不会增长。

这都什么乱七八糟的。

我过去写过关于多样化成长轨迹的重要性——一线员工和经理人——但是我们最近在 Moz 花了大量的时间碰撞想法,很快会实施一个新的职位/团队的结构,最终付诸实践,我对此充满期待。

现在我会为一个在其工作岗位上做的很优秀的一线员工表达对管理的兴趣而担心。我担心这种渴望的很重要的一部分不源自真正的管理责任感,而是因为他们想要在职业生涯和/或影响力上得到提高,并且认为这是唯一的办法。

我画了这张图来辅助说明两种角色之间的不同:

ics-vs-pws-small
(大图)

一线员工为他们自己及其工作负责。因为他们以一线员工的方式取得了长足的发展,所以他们的影响力变得更加广泛。一个在 Moz 的好的例子就是 Dr. Pete,他判断公司的战略指示并随之协力投入。他通过审查来协助大数据操作,通过战术指导和策略输入来辅助市场,发表如此高质量的博客指南,甚至从头开始设计整个项目并基于他们的创意执行。他的影响遍及整个公司,横跨多个团队,和他们一同成长。他通过自己的影响力定义了这个角色,这比其它方式都好。

另一方面,优秀的经理人有义务让他们的团队开心、团结自主,也要负责审查、指导等等。他们发展的越顺利,就越不需要“待在壕沟里”了。很多情况下,他们只会协助定义战略问题。剩下的定义范围、搜索相关答案、实现和执行统统都交给一线员工来做。一个在 Moz 的好的例子就是 Samantha Britney。她长期是一个一线员工,但现如今已经成为了经理人,帮助产品团队的几个一线员工,给予他们工作的自主性,通过工具、资源和协助把事做好,并提供作为一个经理人必要的辅导、一对一、回顾和 HR 工作。她的报告中从不会提及任何细枝末节,但总会驱动他们的项目向前。

基本上,如果你喜欢并且能够把这件事做好,那么你应该做一个一线员工。如果你喜欢 (且擅长) 把自主权交给其他人,帮助他们成长和成功,那么你应该做一个经理人。

这些一线员工和经理人之间有这样一些差别

  • 随着一线员工们的发展,他们希望和经理人的职责范围有更多的重叠。对经理人来说恰恰相反——随着他们的发展,他们实际干的活越来越少。
  • 资深的一线员工的角色更加灵活——他们能够在各种地方工作,并且由于工作得到认可,收到的会议和活动邀约就越来越多。资深的经理人相反——他们在办公室的时间更为关键,所以很少出差,也经常身居幕后 (很明显 CEO 在这方面是一个例外)。
  • 如果你有很多一线员工却只有很少的经理人,那么你会发现汇报和管理很有挑战。但是如果你有一堆经理人而没几个一线员工,你会面临“厨师太多伙计不够了”的问题 (并且这通常意味着你们的组织和文化已经一团糟了)。
  • 优秀的一线员工有时会发展成为经理人,并因此在新的角色上变得平庸或失败。这绝对是个悲剧。公司不仅失去了一个卓越的一线员工,而且连管理也被搞砸了,因为这会造成大量传染式的问题。如果一个一线员工表现平平,问题往往不至于这么严重。
  • 待遇是个技巧活儿。在我理想的世界里 (对了我们在 Moz 创建的工资范围是跨发展路线的),一线员工和经理人的级别是大致等价的。假设在某一条路线上有 7 个级别,那么 level 3 的一线员工可以做 level 3 的经理人的事情。最高级别的一线员工应该能够和 CXO 挣得一样多。

我和他人分享这些观点时,大部分情况是直观的。我遇到过的最大问题和一个简单的概念有关——战略战术的所有权。有一天一个 Mozzer 同事和我在这方面的看法就不一致。他觉得在 Moz 的历史上,有些团队的经理人掌握着战略和战术的所有权。个人开发者没有定义他们做什么,怎么做,如何衡量,也没有定义执行过程,他们只是接受命令。

是的这样做也行得通并且这种情况确实发生过。但是我不同意我的同事,这样做相比于,把更大的所有权交给一线员工,让他们决定做什么、何时何地、如何做,让经理人指决定谁来做已经为什么要做,效果不可能一样。诚然,很多初级经理人和一线员工之间会具有更大的内容重叠,而很多高级个人开发者会决定谁来做和为什么要做 (如上所述)。但是我强烈的相信,从长期来看,我们应该走这条路。人们的快乐便在此之上。

当 Daniel Pink 问道“是什么让我们的工作快乐?”时,答案已经很明显 (并且被很多其他学者和不太正式调查者证实):

  1. 自治——主导我们自己生活的渴望。
  2. 精通——在关键的事情上越做越好的欲望。
  3. 目的——渴望做好比我们自己更重要的事情

如果个人开发者无法控制自己的工作内容并且能够掌握工作技能,他们中间优秀的人就会离开,去那些提供这种机会的公司。我们将只留下经理人,而且这会很快。

很奇怪,我是那种一线员工风格的 CEO (也许这并不都是奇怪)。我是一个高级别的一线员工,所以我和经理人有很大的职责重叠,但是我会服务所有的团队、工作和细节。我可能是最直接参与到产品和市场的人,我也经常让这些团队 Mozzer 们像对待资源和工具一样对待我。你让我写篇博客我就会去写,你让我答复一个客户我就会冲上去,你需要聊聊一个项目如何匹配更广泛的目标,以及如何改变你的做法,那就一起聊聊呗。我喜欢我汇报给这些 Moz 员工的感觉——而不是其它方式。我想这件事情永远也不会改变。

p.s. 我很喜欢 Phil Scarr 的这篇文章,它描述了自己从经理人转变为一线员工的经历以及为什么。Carin 从带领着我们的大数据团队,转变为一个产品团队的资深一线员工,我为之感到骄傲。

p.p.s. 如果我的思路不对 (或者对) 而你也有相关的经验,不妨也留言给我。我一定虚心学习——因为我一直在提醒自己,我是第一次当 CEO

如何撰写 Git 提交信息

译自:https://chris.beams.io/posts/git-commit/


介绍:为什么好的提交信息非常重要

如果你浏览任何 Git 仓库的日志,你可能会发现那些提交信息多少有些混乱。比如,看看这些我早年提交给 Spring 的精品

$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"

e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing

,比较一下这个仓库最近的提交

$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"

5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage

你更喜欢读哪个呢?

过去的信息从长度到形式都很多样;最近的信息比较简洁且一致。过去的信息是一般情况下会发生的;最近的信息绝不是偶然发生。

虽然很多仓库的日志看起来像是过去的,但也有例外。Linux 内核和 Git 自身就是伟大的例子。再比如 Spring Boot 或其它由 Tim Pope 管理的仓库。

这些仓库的贡献者知道,对于一个开发同事来说 (其实对未来的自己也是一样),一条用心撰写的 Git 提交信息是用来沟通这则改动最好的上下文。一个 diff 会告诉你什么改变了,但是只有提交信息能正确的告诉你为什么。Peter Hutterer 阐述得非常好:

重建一段代码的上下文是非常费时费力的,这是无法完全避免的。所以我们应该努力尽可能的减少它。提交信息可以帮上这个忙,也正因为此,一个提交信息反应了一名开发者是不是个好的协作者。

如果你对于创建一个伟大的提交信息还没有想过太多,那说明你可能还没有在 git log 及相关的工具上花费太多的时间。这里有一个恶性循环:因为提交历史不成体系且不一致,我们就不会花更多的时间使用和关心它。因为它得不到使用和关注,所以它就一直不成体系且不一致。

但是用心写出来的日志是美丽且实用的。git blamerevertrebaselogshortlog 以及其它子命令就是生命的一部分。回顾其他人的提交和 pull requests 变成了值得去做的事情,并且可以快速独立完成。理解最近几个月或几年为什么发生了这些事情不止是可能的并且是高效的

一个项目的长期成功靠的是其可维护性,以及一个拥有比项目的日志更强大的工具的维护者。这里值得花时间学习一下如何正确的考虑它。一开始可能是个麻烦的东西很快会变成习惯,并且最终变成一切投入的自豪和产能的源泉。

在这篇文章中,我只会致力于保障一个健康的提交历史的最基本要素:如何撰写一份个人提交信息。这里还有其它重要的实践比如压缩提交 (commit squashing) 就不是我在这里想说的。可能会为此写一篇吧。

大多数编程语言都建立了良好的编码规约,以形成惯用的风格,比如命名、格式化等。当然在这些编码规约中有一些差异,但是大多数开发者赞同取其一并养成习惯好过每个人都选择自己的风格而发生混乱。

一个团队的提交日志方法应该是一致的。为了建立一个有用的修订历史,团队应该首先约定一个提交信息的规约,该规约至少定义以下三方面:

样式。标记句法、缠绕边距、语法大小写标点符号。把这些东西都找出来,去除猜测,把规则定的尽量简单可行。最终的产出将会是不同寻常的一致的日志,不只是乐于阅读,实际上也让阅读变成了一种习惯

内容。提交信息的正文 (body) (如有) 应该包含什么样的信息?不应该包含什么?

元数据。Issue 追踪 ID、pull request 号等信息如何放进来?

幸运的是,这里有一些已经被良好建立的规约,用来创建惯用的 Git 提交信息。事实上,有些规约中很多都是以某种 Git 命令的方式工作的。不需要你重新发明任何东西。只需遵循下面七大法则,你就可以像专家一样进行提交:

伟大的 Git 提交信息七大法则

注意:这些 法则 之前 在别的地方 提到过

  1. 用一个空行把主题和主题隔离开
  2. 把主题行限制在 50 个字符以内
  3. 主题行大写开头
  4. 主题行不必以句号结尾
  5. 在主题行中使用祈使句
  6. 正文在 72 个字符处折行
  7. 使用正文解释是什么为什么而不是怎么样

比如:

Summarize changes in around 50 characters or less

More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.

Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.

Further paragraphs come after blank lines.

 - Bullet points are okay, too

 - Typically a hyphen or asterisk is used for the bullet, preceded
   by a single space, with blank lines in between, but conventions
   vary here

If you use an issue tracker, put references to them at the bottom,
like this:

Resolves: #123
See also: #456, #789

1. 用一个空行把主题和正文隔离开

git commit 的 manpage 手册中写到:

虽然不是必须的,但是你最好以一句少于 50 个字符的话简短概括你的改动,然后空一行,再深入描述。提交信息中空行之上的文本会被当作提交的标题,该标题在 Git 中到处都会用到。比如 Git-format-patch(1) 会把一个提交转换为一封电子邮件,它会把这个标题作为邮件的主题,其余的部分会作为邮件的正文。

首先,不是每一次提交都同时需要一个主题和一段正文。有的时候单独一行就可以了,尤其是当改动很简单没有更多必要的上下文的时候。比如:

Fix typo in introduction to user guide

无需说更多;如果读者好奇到底修复了什么 typo,她可以通过诸如 git showgit diffgit log -p 简单看看改动的内容就可以了。

如果你是在命令行中提交,则很容易使用 git commit-m 选项:

$ git commit -m"Fix typo in introduction to user guide"

然而,当一个提交值得一些解释和上下文的时候,你需要撰写正文。比如:

Derezz the master control program

MCP turned out to be evil and had become intent on world domination.
This commit throws Tron's disc into MCP (causing its deresolution)
and turns it back into a chess game.

带正文的提交信息并不便于通过 -m 选项来撰写。你最好找一个合适的文本编辑器撰写信息。如果你并没有在命令行中为 Git 设置过编辑器,那么请移步阅读 Pro Git 的这个章节

当你在任何情况下浏览日志的时候,都会觉得把主题从正文中分离出来是值得的。这里有一整段日志:

$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <kevin@flynnsarcade.com>
Date:   Fri Jan 01 00:00:00 1982 -0200

 Derezz the master control program

 MCP turned out to be evil and had become intent on world domination.
 This commit throws Tron's disc into MCP (causing its deresolution)
 and turns it back into a chess game.

现在运行 git log --oneline,这个命令只会打印主题行:

$ git log --oneline
42e769 Derezz the master control program

或者,git shortlog,这个命令会把提交按照用户分组,同样出于简洁的考虑只会打印主题行:

$ git shortlog
Kevin Flynn (1):
      Derezz the master control program

Alan Bradley (1):
      Introduce security program "Tron"

Ed Dillinger (3):
      Rename chess program to "MCP"
      Modify chess program
      Upgrade chess program

Walter Gibbs (1):
      Introduce protoype chess program

在 Git 里还有一些其它的情况下,会区分主题行和正文——但是如果没有它们中间的空行的话是不会正常工作的。

2. 把主题行限制在 50 个字符以内

50 个字符并不是一个严格的限制,只是个经验之谈。保持主题行的长度以确保它可读且促使作者考虑一下最简略的表达方式足矣。

提示:如果你做总结很艰难,你可能是一次性提交太多东西了。把原子提交从中剥离出来吧 (每个主题是一个独立的提交)。

GitHub 的 UI 都会提醒这些规约。如果你输入超过 50 个字符的限制,它会警告:

gh1

而且会主题行超过 75 个字符的部分会被截断,留下一个省略号:

gh2

所以奔着 50 个字符去写,但是 72 个字符是底线。

3. 主题行大写开头

如题。比如:

  • Accelerate to 88 miles per hour

而不是:

  • accelerate to 88 miles per hour

4. 主题行不必以句号结尾

主题行结尾的标点符号用法不是必要的。而且,当你打算控制在 50 个字符以内时,连空格都是很宝贵的。比如:

  • Open the pod bay doors

而不是:

  • Open the pod bay doors.

5. 在主题行中使用祈使句

祈使句就是指“说起来或写起来像是在发号施令”。举几个例子:

  • Clean your room
  • Close the door
  • Take out the trash

其实这七大法则的每一条读起来都是祈使句的 (“正文在 72 个字符处折行”等)。

祈使句听起来有一点粗鲁;这也是我们为什么不常用它的原因。但是这非常适合写在 Git 提交的主题行中。其中一个的原因就是 Git 本身就是根据你的意志命令式的创建一个提交的

例如,使用 git merge 的默认信息读起来是这样的:

Merge branch 'myfeature'

而用 git revert 的时候是:

Revert "Add the thing with the stuff"

This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

再或者在一个 GitHub pull request 上点击“Merge”按钮时:

Merge pull request #123 from someuser/somebranch

所以当你以祈使句撰写你的提交信息时,你遵循了 Git 自己内建的规约。比如:

  • Refactor subsystem X for readability
  • Update getting started documentation
  • Remove deprecated methods
  • Release version 1.0.0

这样撰写一开始会觉得有点怪怪的。我们更多的在说话的时候使用陈述句来陈述事实。这是为什么提交信息经常读起来像:

  • Fixed bug with Y
  • Changing behavior of X

有的时候提交信息写起来像是对于其内容的描述:

  • More fixes for broken stuff
  • Sweet new API methods

为了避免混淆,这里有一个简单原则,可以用在每一个地方。

一个 Git 提交的主题行的准确的格式应该始终完全遵循下面的句式:

  • If applied, this commit will 这里是你的主题行

比如:

  • If applied, this commit will refactor subsystem X for readability
  • If applied, this commit will update getting started documentation
  • If applied, this commit will remove deprecated methods
  • If applied, this commit will release version 1.0.0
  • If applied, this commit will merge pull request #123 from user/branch

注意非祈使句在这里别扭的地方:

  • If applied, this commit will fixed bug with Y
  • If applied, this commit will changing behavior of X
  • If applied, this commit will more fixes for broken stuff
  • If applied, this commit will sweet new API methods

注意:使用祈使句只在主题行中至关重要。当你撰写正文的时候就可以放下这些限制了。

6. 正文在 72 个字符处折行

Git 不会自动给文本折行。当你为一个提交撰写消息正文的时候,你必须意识到它正确的边距,并且手动折行。

这里推荐在 72 个字符处折行,这样 Git 有足够的空间,即便缩进文本也可以保证所有东西在 80 个字符以内。

一个好的文本编辑器是可以帮上忙的。比如在 Vim 中配置在 Git 提交的 72 个字符处折行非常容易。然而传统的 IDE 在给提交信息文本折行方面提供的智能支持很糟糕 (尽管 IntelliJ IDEA 在最近的版本中终于在这方面做得好一些了)。

7. 使用正文解释是什么和为什么而不是怎么样

这个来自比特币核心的提交是一个非常好的解释改动是什么和为什么的例子:

commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date:   Fri Aug 1 22:57:55 2014 +0200

   Simplify serialize.h's exception handling

   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.

   As exceptmask always included 'failbit', and setstate was always
   called with bits = failbit, all it did was immediately raise an
   exception. Get rid of those variables, and replace the setstate
   with direct exception throwing (which also removes some dead
   code).

   As a result, good() is never reached after a failure (there are
   only 2 calls, one of which is in tests), and can just be replaced
   by !eof().

   fail(), clear(n) and exceptions() are just never called. Delete
   them.

看一眼完整的 diff,想一下作者此时此刻通过提供这样的上下文为同事以及未来的提交者节省了多少时间。如果他不这样做,这些信息可能永远找不回来了。

在很多情况下,你可以忽略这个改动发生时的各种细节。从这个角度看,代码自己会说话 (如果代码很复杂以至于需要长篇大论的解释,那也是代码注释该做的事情)。请首先专注于弄清你产生这个改动的理由——改动前的工作方式,改动后的工作方式 (以及这样做哪里不对),以及为什么你决定以这样的方式解决问题。

你将来某一天维护它的时候也许会感激今天的你!

提示

学者爱上命令行。远离 IDE。

[和 Git 子命令同样多的原因][For-as-many-reasons-at-there-are-Git-subcommands],拥抱命令行是明智的。Git 是超级强大的;IDE 也一样,但是套路不同。我每天都使用 IDE (IntelliJ IDEA) 也用过很多其它的 (Eclipse),但是我从未见到 IDE 对 Git 的集成能够配得上命令行的易用和强大 (一旦你意识到这一点)。

某些 Git 相关的 IDE 功能是非常宝贵的,比如当你删除一个文件时调用 git rm、当你重命名一个文件时完成相应的 git 命令。但是当你尝试提交、合并、rebase、或通过 IDE 做复杂的历史分析时,事情就分崩离析了。

当你想发挥出 Git 全部的能量的时候,命令行始终是不二之选。

记住不论你是用的是 Bash 还是 Z shell,都有 tab 补全脚本减轻忘记子命令和开关的痛苦。

阅读 Pro Git

Pro Git 这本书已经可以免费在线阅读,这本书非常棒。用好它吧