Soft_Job 板


LINE

Linus Torvalds 曾写了一本书提到,当初创造 Linux 只是因为好玩,却意外掀起一场 革命。Git 是 Linus 的第二代表作,同样也是意外的革命,是现在软体工程师的标配, 但至少对 Linus 本人来说,它的起源可就没这麽好玩了。 图文完整版:https://blog.brachiosoft.com/posts/git/ 脸书专页:https://www.facebook.com/brachiosoft # Linus 扩展不了 1998 年是 Linux 风光的一年,许多大公司,如昇阳、IBM 和甲骨文,都纷纷投入 Linux 的业务。那年春天,Linus 的二女儿出生,他们一家从芬兰搬到美国加州也差不多一年 ,生活步入正轨。虽然 Linux 还尚未给 Linus 带来什麽收益,但 Linus 也可算是事业 家庭两得意。 反观 Linux Kernel 的开发者社群,随着愈来愈多人加入开发,既有的合作方式开始力 不从心。Linus 开始显得没办法跟上开发者们修改程式码的速度,逐渐成为瓶颈。 1998 年 9 月 28 日,Linus 和往常一样,读着 Linux Kernel 邮件列表上的信。 > 请不要浪费时间送修补了,这些在 vger 上早就修好了。 Linus 看到这句话不太高兴。一直以来,Linux 程式码的修改重度仰赖 Linus 本人, Linus 本人就是版本控管。如果你要修改程式码,寄封信到邮件列表上,Linus 看到了 并认可,就会将你的修补送进他自己的版本,然後不时在 FTP 上释出新版本。Linus 喜 欢这样的合作方式,因为他可以掌控一切变更,大家也信任 Linus,觉得 Linux 本来就 该由 Linus 掌控。 但自从 David Miller,一位 Linux Kernel 的资深开发者,架设了一个名为 vger 的 CVS 伺服器,有些人就以为可以绕过 Linus 本人,将变更送到 vger 就没事了。这不是 Linus 第一次遇到同样的问题,他在邮件列表上不悦的回应: > 「在 vger 上就不要浪费时间」这个说法完全是愚蠢的,因为 vger 上很多东西可能 > 永远都不会进 2.2。 於是几个开发者与 Linus 展开一场激烈的笔战,他们开始陈情,说 Linus 回信太慢, 甚至有时候要寄三次才会得到这个「仁慈独裁者」的亲回。 「这些家伙也不照照镜子,」Linus 心想:「我一天要看多少信,如果连寄三次信都嫌 麻烦,那这个修补我宁可不要。」 Linus 在讨论串留下这个讯息随即怒离: > 这次的讨论只是让我烦燥,增加我的压力。走开吧,不要再 CC 我了,我要度假去了 > ,我不要再听到任何有关它的事。总之,滚出我的信箱就对了。 Linus 情绪性的发言反而让一些人开始提出正面的帮助。 开源运动代表人物之一 Eric S. Raymond,着名文章《大教堂和市集》就是他写的。看 到 Linus 的怒离文,他冷静地呼吁: > 各位,这些是职业倦怠的早期徵兆。Linus 一直以来的毅心确实令人敬佩,但他也是 > 有极限的。我们所有人(是的,也包括你 Linus)要一起想办法帮这个重要人物减少 > 压力,而不是增加压力。 另一位伸出援手的是 Larry McVoy,在一篇标题为「成长痛的解决方案」的邮件,他这 麽写: > 问题症结在於 Linus 扩展不了("Linus doesn’t scale")。我们不能期待 Linus 一 > 个人能跟上 Kernel 变化的速度,我们也不想看到 Linus 失去对 Kernel 的掌控,他 > 已一再证明自己非常适任此职。 > > (解决方案基本上是)将工作分担给 Linus 身边的几个人,要做到分担,我们要导入 > 新工具。 > (这个新工具是)一个分散式版本控管系统... Larry 当时正好在开发一套新的版控软体,叫做 BitKeeper。 # BitKeeper 的起源 在 1990 年代早期,昇阳导入了一套名为 Network Software Environment (NSE) 的内 部工具来管理程式码,但 NSE 太慢了,使用体验极差,有些工程师甚至为此愤而离职。 Larry McVoy 不仅是个资深的作业系统开发者,过去也做过许多效能相关的工作,所以 昇阳的主管就找上了 Larry 来调教一下 NSE 的效能。 Larry 一看 NSE 的程式码吓了一跳,「这东西很多地方当初设计时都没有考量到效能。 」他还发现 NSE 的底层其实是 SCCS,SCCS 是 1970 年代的版本控管软体,出现比 CVS 和 Subversion 还早。与其修改体质不良 NSE,Larry 选了另一条路:他用 Perl 写了 NSElite,在 SCCS 之上实作了 resync/resolve 指令,基本上类似现今 Git 的 clone/pull/push 指令。 NSElite 比 NSE 快多了,所以昇阳的工程师一个一个背弃 NSE,改用 NSElite。昇阳某 VP 见状,觉得有商机,就组了一个八人团队,想要用 C++ 重写 Larry 写的 Perl 脚本 ,将其产品化为 TeamWare。 TeamWare 大概是最早的分散式版控系统,後来昇阳 Solaris 作业系统的开发全是藉助 於它。工程师们用过 TeamWare 都表示回不去了:不同於 CVS 和 Subversion,TeamWare 让你将整个专案复制到你自己的机器,你可以尽情地在本地端提交变更,等到准备好再 将你自己本地的版本合并回远端版本。 这八人团队的成员本来是写 C 语言的,当时 C++ 是新的火热语言,他们边学 C++ 边开 发 TeamWare。在 TeamWare 还未完成前,Larry 曾尝试继续开发 NSElite,但这无疑是 给 TeamWare 团队难堪:一个人用 Perl 竟然比八个人用 C++ 还来得快,VP 见状便告诉 Larry:「这件事已经上报给 Scooter(即 Scott McNealy,昇阳的执行长),如果你再 发布一次,你就被解雇了。」 为此,1991 年,Larry 停止 NSElite 的开发,但建造一个分散式版控软体的念头始终 在他心中挥之不去。他本来以为会有其他商用软体会跟进 TeamWare 的脚步,但并没有 。1997 年 Larry 开始着手开发一款名为 BitKeeper 的分散式版控软体。然而,直到 1998 年 9 月,当他看到邮件列表上 Linus 处於崩溃边缘,这才真正激励他开始认真看 待 BitKeeper 这个专案。 # Linux Kernel 采用 BitKeeper 1998 年秋天某日,Larry 邀请了 Linus Torvalds、David Miller、Richard Henderson 来家中,吃完晚餐後,他们席地而坐,开始协商对策要如何减少 Linus 的工作量。他们 在地板画了三、四个小时的图,这些图大致上就是 TeamWare 在昇阳内部行之有年的运 作方式,Larry 对此十分熟悉。 在这个框架中,开发者们可利用 BitKeeper 各自开发,不互相干扰,而且在 Linus 这 边做最後整合时,能够不失去修改的历史记录,让 Linus 能看出一个变更的来龙去脉, 审查程式码时更容易。 「好吧,如果你做出来,而且跑起来跟你说的一样,我就会用它。」Linus 说道。 「没问题,这我以前做过,大概需要六个月。」Larry 回答。 Larry 马上就意识到他低估了问题的复杂度,所以他成立了一间名为 BitMover 公司, 找了几个熟悉版控系统的好手,一起打造 BitKeeper。19 个月後,2000 年 5 月, BitKeeper 公开释出第一版,此时 BitMover 是一个七人团队。 第一版的 BitKeeper 有一个命令列工具 bk,也有一些图形介面的工具。其中 bk clone/pull/push 命令作用有犹如 git clone/pull/push。 当时昇阳的 TeamWare 已是有口皆碑,而 BitKeeper 更是 TeamWare 的强化版。例如, TeamWare 只允许在 NFS 档案系统间传递资料,而 BitKeeper 可以走 HTTP 来传输档案 ,实现了真正的分散。因此不久後,BitKeeper 就为 BitMover 带来充沛的现金流,到了 2002 年,BitMover 团队成长到了 25 人,完全自给自足,没靠外部资金。 2002 年 1 月,Linus 工作量太大的问题又再度浮现,开发者送出的修补不是等很久才 迟迟回应,不然就是被忽略。有人写了一篇「小小的提议」尝试改善这个问题。讨论串 中,有人随口提到「bitkeeper 真是个好工具」,唤醒了三年前,Larry 家中的那顿晚 餐,在 Linus 脑中种下的那颗种子。Linus 问道:「有多少人在用 bitkeeper 做 kernel 开发?」 果不其然,当时已经有些 Kernel 开发者早就在使用 BitKeeper。Linux PowerPC (PPC) 团队早在 1999 年 12 月就开始试用 BitKeeper,BitMover 为了帮助他们,架设了 bkbits.net 伺服器。 过没几天,2002 年 2 月 5 日,邮件列表上就看到 Linus 开始在测试 BitKeeper。此 後,Linux Kernel 主要开发者们也跟进开始采用 BitKeeper。你不一定要用 BitKeeper 才能参与开发,但如果你是 BitKeeper 的使用者,流程大概是: # 下载仓储(repository) bk clone bk://linux.bkbits.net/linux-2.5 linux-2.5 bk clone linux-2.5 alpha-2.5 # 从另一个地方下载变更 cd alpha-2.5 bk pull bk://gkernel.bkbits.net/alpha-2.5 # 编辑档案并将变更上传回远端 bk vi fs/inode.c bk push bk://[email protected]/alpha-2.5 若要将变更送给 Linus,你就再寄封信到邮件列表上,内容大致是: Here is an update for something something... Please pull from: bk://gkernel.bkbits.net/alpha-2.5 example/file1.c | 6 ++++++ example/file2.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) # 没有免费的 BitKeeper 了 Larry McVoy 让 Linux Kernel 开发者免费使用 BitKeeper,但免费是有代价的。例如 ,他们的免费用户的使用执照里规定: * 你不可以关掉 Open Logging──此机制会将使用纪录传送至 BitMover 伺服器。 * 如果你从事的是版控软体的业务,你不可以免费使用 BitKeeper。 * 如果你要让 BitKeeper 和其他同类软体一起运行,你必须徵求 BitMover 同意。 Linux 是开源软体的始祖,社群里有很多自由软体的拥护者,对这些条款不是嗤之以鼻 ,就是敬而远之。可是对 Linus 和主要的 Kernel 开发者来说,重点是 BitKeeper 减 轻了他们的工作量,况且当时没有更好的替代工具,他们也就接受 BitKeeper 的使用条 款,以换取它的便利。 以 Linus 来说,他对专用软体(proprietary software)一直持开放态度,他当初会选 用自由软体 GPL 作为 Linux Kernel 的授权协议,纯粹是因为他不乐见商业市场「玷污 」了 Linux,他的方法就是让 Linux 保持开放,而GPL 刚好在那边符合他的需求,他就 拿来用了。但他从不觉得所有软体都该走自由软体的路线,他觉得作者有权以任何他想 要的方式散布软体,怎麽使用软体不应该是社会运动。 自由软体的拥护者可不这麽想,比较极端的甚至会认为专用软体都是邪恶的。这群骇客 宁可拥有修改软体的自由,也不要 BitKeeper 的「便利」。 Larry 备受来自社群的压力,为解决此问题,BitKeeper 团队在 2003 年架设了一个 BitKeeper 至 CVS 的镜像,让那些不想装 BitKeeper 的人,也可以透过 CVS 来取得程 式码的修改历史。但从 CSV 取得的历史资料和 BitKeeper 上的并不完整,人们还是不 满意:「为什麽我们的资料要被锁在 BitKeeper 的专用格式里,而且还明文禁止我们用 其他程式去读取我们自己的资料?」 有监於此,Samba 和 rsync 的作者,澳洲程式设计师 Andrew Tridgell(简称 Tridge ),在 2005 年 2 月开始着手写一个免费的 BitKeeper 客户端程式,要解决自由软体 用户面临的问题。 Tridge 做了以下尝试。 「这里有一个 BitKeeper 位址,bk://thunk.org:5000,用 telnet 连上去试试看。」 $ telnet thunk.org 5000 Trying 69.25.196.29... Connected to thunk.org. Escape character is '^]'. 「连上去了,何不输入 help 命令?」 help ? - print this help abort - abort resolve check - check repository clone - clone the current repository help - print this help httpget - http get command [...] 「BitKeeper 伺服器居然这麽好心,列出所有指令。」 「所以 clone 应该就是下载仓储用的指令吧?」 他接着输入 clone,发现输出仅是一连串 SCCS 格式的档案。至此,「反向工程」的工 作已大功告成,剩下的只是把程式写出来。 不知 Linus 是从何得知 Tridge 在干的事,或许是 Tridge 自己私下告诉他的。总之, Linus 得知後就将这件事告诉他的好朋友 Larry。Larry 听到後无法接受,因为一个免 费的第三方客户端会毁了 BitKeeper 的商业模式,於是 Larry 连手 Linus 和时任 OSDL(即现在的 Linux 基金会)执行长的 Stuart Cohen,要求 Tridge 停手。 Stuart Cohen 选择冷处理,觉得这不关 OSDL 的事。但 Linus 非常不想失去 BitKeeper,所以很努力地居中调解,试着找到出双方都能接受的折衷方案。Tridge 坚 定地认为他没错,他甚至认为有一个第三方客户端对 BitKeeper 和 Kernel 开发者们是 双赢 。他在 2005 年 4 月在 Freshmeat(後来并到 SourceForge)发布 SourcePuller ,里面的 README 文件写道: > 有一个开源的客户端本应是一大进步,BitMover 可以在商业环境继续成长,自由软体 > 社群也能使用并从中受益。 > > BitMover 有权为 BitKeeper 制定使用规范。当然,BitMover 这样描绘我,我很失望 > 。但请理解他们承受了很大的压力,而在压力大的情况下,人们会说错话。 Larry 不认同这会是双赢,支持 Kernel 的开发是要成本的,没收钱的就算了,还可能 会违害到既有的商业模式,所以为了维护 BitMover 的生计,他选择撤下 BitKeeper 的 免费使用执照。 Linus 交涉了几个礼拜,也不想再当和事佬了。这下没有免费的 BitKeeper 可以用, Linus 怒了,他公开在论譠上责备 Tridge,说他「破坏别人的创新」、「恶搞别人」。 当然,Linus 大可付钱,但他没办法要求其他 Kernel 开发者也付钱使用 BitKeeper, 所以他必须另辟途径。贴文中他写道: > 现在,我得收拾善後。因为最好的版控工具不能用了,我会自己写一个给 Kernel 用 > 。但没关系──我自己的问题,我自己解决,谢谢你了(Tridge)。 2005 年 4 月 6 日,Linus 在邮件列表上宣布 Linux Kernel 与 BitKeeper 要分手的 消息。他首先感谢 Larry 和他团队这三年来的帮助。接着他说他会离线一个礼拜,找出 一个替代方案。最後他提到: > 用不着跟我说 subversion 了,如果你真的想给建议,去看看 monotone,它应该是最 > 可行的替代方案。 # Monotone Monotone 的原作者是 Graydon Hoare。2001 年,住在加拿大的 Graydon 和他澳洲朋友 为了让跨时区合作更容易一些,他们打造了一个类似现在的持续整合(CI)系统(当时 CI 还不是显学),确保程式码无时无刻都通过测试。 2002 年,Graydon 开始对版本控管结合 CI 产生兴趣,当时他找到只有 Aegis 有这样 的概念。同时,Graydon 又看到朋友使用 BitKeeper,他想到 Aegis 结合分散式版控应 该是不错的机会,Monotone 就此应运而生。 值得一提,Graydon 後来加入 Mozilla,并创造了 Rust 程式语言。 好巧不巧,Linus 挑了一个坏的时机点来把玩 Monotone。原本 Monotone 0.7 性能还算 快,但自 0.14 开始,Monotone 的开发者开始加入许多验证机制。就在 Linus 下载 Monotone 前,原作者 Graydon 发布 0.17 後就跑出度假了,里头加了一堆严谨的检查 程式码,以确保资料写入资料库前是正确的,但这些程式码尚未优化,反而拖慢了性能 。在 0.17 的发布纪录提到: > pull 命令可能会非常慢,而且占用很多 CPU 有人测试用 Monotone 下载它自己,竟然花了两小时,其中 71 分钟是 CPU 时间。 「没有腿的树懒可能都比它快。」那位人士如此形容。 Linus 向 Monotone 的开发者回报性能问题。2005 年 4 月 10 日,Monotone 0.18 释 出,许多操作都至少快了一倍。虽然 Linus 也名列在 0.18 的贡献名单中,但根据 Monotone 开发者之一 Nathaniel Smith 的说法: > Linus 其实没有对 Monotone 贡献过任何程式码,或者据我所知,他也没有对 git 以 > 外的任何版控软体贡献过程式码。除了「这太慢了!」之外,他也没有提出什麽实质 > 建议 ;-)。他之所以名列为贡献者,是因为在与他的讨论中,我找到了一个测试案例 > ,追踪到一个重大性能瓶颈。我曾犹豫是否应该把他的名字列上去,因为这可能会让 > 人产生奇怪的想法,但我想,如果是其他人我也会这麽做,所以...(耸肩) 与此同时,受到 Monotone 的设计启发,Linus 也从零开始,开始着手写了一些 C 程式 码。 # Git v0.01 初探 2005 年 4 月 7 日,Linus 上传了一个名叫 Git 的东西,他在邮件列表写道: > 这边有一个小小的挑战要给疯狂的骇客们,如果你有想玩玩看很乱(但非常快)的东 > 西,看一下 kernel.org:/pub/linux/kernel/people/torvalds/ > > 第一个将 sparse-git 的变更纪录树寄给我的,将会得到一个金色星星和公开表扬, > 我在里头放了很多线索。 这是 Linus 第一次在公开场合提到 Git。 该网址有以下档案和目录: git.git/ 09-Apr-2005 16:09 - sparse.git/ 07-Apr-2005 20:07 - git-0.01.tar.bz2 07-Apr-2005 14:25 39K git-0.01.tar.bz2.sign 07-Apr-2005 14:25 248 git-0.01.tar.gz 07-Apr-2005 14:25 40K ... sparse-git.tar.bz2 08-Apr-2005 17:26 15M git-0.01.tar.bz2 里的 C 程式码加起来大约 1000 行。 有别於现在的 Git 有一个单一执行档 git,Linus 最早上传的 Git ,编译後会产生七 个独立执行档。 init-db 做的事情很单纯,它会在当前目录下建立一个名为 .dircache/objects 的目录 ,然後在 .dircache/objects 里,再建立 256 个以十六进位数字编号的子目录,依序为 00, 01, 02, ..., 0f, 10, ..., ff。 .dircache/objects 目录代表着一个物件资料库,物件的种类有: * 二进位资料(blob)──即档案内容。 * 树(tree)──即目录,本质上是一些档案(二进位资料)和目录(树)的名称。 * 变更集(changeset)──由两棵树的名称定义而成,意义上代表的是 A 树变更成为了 B 树。「变更集」是 Git 早期的用词,之後成为「提交」(commit)。 这里物件的名称不是档名或目录名,而是物件内容压缩後的 SHA-1 杂凑。这个设计是 Linus 从 Monotone 学来的,差别在於 Monotone 底层使用 SQLite 储存 SHA-1 物件名 称和内容,而 Linus 选择直接使用系统呼叫和档案系统。 SHA-1 几乎具有唯一性,因此我们可以假设 Git 资料库中不会有两个不同名、但相同内 容的物件。假如有个物件的名称是 ba93e701c0fe6dcd181377068f6b3923babdc150,Git 就会将它储存在 .dircache/objects/ba/ 目录下,一个名为 93e701c0fe6dcd181377068f6b3923babdc150 的档案。 这七个执行档就是以这个「内容可定址」(content-addressable)档案系统为中心的七 种操作。例如: * write-tree 建立一个树物件,即将某个时间点树的样子写到资料库。 * commit-tree 建立一个变更集,即在资料库中连结两棵树,类似现今的 git commit 命令。 * update-cache 加一个档案到 .dircache/index 索引中,类似现今 git add 将档案加 到预存区(staging area)。 Linus 当时看到 Monotone 是如何利用 SHA-1 为物件命名,就立刻爱上这个点子,原因 无他,就是「简单」二字。「简单」也是 Linus 欣赏 Unix 的原因。在《只是为了好玩 》一书,他这麽形容 Unix: > Unix 让我(和大多数人)着迷的地方,就是它简单的设计。在 Unix 中,几乎所有事 > 都可以用六个基本操作(称为「系统呼叫」)来完成。 > > 它给你几种不同形状的积木,足以用来建造所有东西,乾净的设计就该是这个样子。 Git 也是如此,它的资料模型比 CSV、Subversion、BitKeeper 都要简单。它储存的东 西基本上就是改变前和改变後的树,如此而已。它没有在管哪个档案、在哪一行做了什 麽改变,它也不需要,因为改变前後的树就埋有这些资讯。 Linus 用两天写出来的 Git 原型,功能简单,没有多余的验证,没有关联式资料库,只 有 C 程式码、SHA-1 杂凑、系统呼叫,完全针对 Linus 自己的需求订制。而 Monotone 专案当时迈入第三年,功能完善,还要应付各种场合需求。再加上 Monotone 原作者 Graydon 加了一堆未优化的程式码後跑去度假,家里没大人。因此在速度上,Monotone 当时自然是比不过 Git 。 Linus 当初上传的档案 sparse-git.tar.bz2,应该是史上第一个 Git 仓储。Sparse 是 Linus 於 2003 年写的一个 C 语言的静态分析器。如果你还对 Linus 出的挑战题有兴 趣,sparse-git.tar.bz2 解压缩後稍微修改就可以用现今的 git log 命令去读取变更纪 录: # 假设你在 sparse-git 目录下 mv .dircache .git mkdir .git/refs git log # Git 早期贡献者 初版 Git 引来热烈讨论,过没几天,Linus 就开设了 Git 专用的邮件列表,这让 Linux Kernel 邮件列表能够稍微回归正题。头一个月,Git 邮件列表就出现了约 2600 则讯息,而 Linux Kernel,史上合作人数最多的软体专案,同期每月有 7000-9000 则 讯息。 对在版本控管领域耕耘已久的专家们来说,Git 只是「另一个专案」,因为 Linus 最初 上传的 Git 只有一些低阶操作,连 clone 和 merge 的命令都没有,离真正可用的版控 软体还差得远。而 Linus 在说 Git 多快多棒时,无意间贬低了其他版控软体,这让以 BitTorrent 闻名的 Bram Cohen 很不满意,杠上 Linus。 Bram 当时正在推广他自己的同类产品 Codeville。Codeville 在当时已经是个成熟的版 控软体,媲美 Monotone,并且内建十分聪明的合并演算法。看到 Linus 如何与 Git 的 早期追随者讨论合并演算法,Bram 觉得 Linus 根本就是门外汉在重造轮子,称 Git 只 是个「周末小专案」。 Bram 说的有道理,但这个小专案不是一般人的小专案,它是 Linus Torvalds,Linux Kernel 创始人的小专案。身为开源软体界的民间英雄,Linus 的一举一动都是万众瞩目 ,年轻开发者景仰他,视他为傍样。因此在 Linus 上传 Git 後,随即吸引到一群新血 参与讨论和开发。 其中一个早期贡献者是来自捷克的 Petr Baudis。Linus 宣布 Git 的消息当天,Petr 就下载了程式码,为之着迷,并开始贡献。首先,监於早期的 Git 很难用,Petr 在 Git 的基础上开发了 git-pasky(pasky 是 Petr 的别名),这个专案後来成为 Cogito。如果将 Git 的基础是水管工程(plumbing),Cogito 就是陶瓷(porcelain) 马桶和洗手台,它将 Git 包装得更容易使用。 在软体开发用语中,将低阶基础建设比喻成水管工程的用法已不可考,但「陶瓷」一词 用来指高阶的包装工作最早起源自 Git 邮件列表。至今,Git 内部仍使用 plumbing 和 porcelain 二词来称呼低阶和高阶命令。 此外,Petr 还架设了 Git 第一个专案首页 git.or.cz,以及源码托管服务 repo.or.cz。这两个网址一直算是 Git 的「官方」网站──直到 GitHub 取代了它们。 Petr 是从外部贡献,在 Git 基础之上向上堆叠,向外架设服务。另一个早期贡献者, 滨野纯(Junio Hamano)则是从内部切入,直接贡献 Git 本身。後来他是更从 Linus 手上接下 Git 维护人的工作,直到今天。 # 接班人 滨野纯(Junio Hamano)是一个来自日本的软体工程师。大概是 1995 年,毕业後工作 不到一年,他就被他任职的公司 Twin Sun 派到洛杉矶,从此在美国定居。在那里,他 遇到了当时也在同公司工作的 Paul Eggert。 Paul Eggert 维护过许多自由或开源软体专案,包括 RCS(一个更早的版控软体)和 Tar。目前,他是 UCLA 大学的教授,也是时区资讯资料库的维护人。 滨野纯受到 Paul 的影响,对开源软体的世界产生兴趣。尽管他并非 Kernel 开发者, 他仍订阅了 Linux Kernel 等开源专案的邮件列表,纯粹因为好玩。 2005 年 4 月,滨野纯在邮件列表上看到 Linux Kernel 与 BitKeeper 要分手的消息。 滨野纯一直想要在开源软体界大展身手,而这个叫做 Git 的东西便是个好机会──全新专 案,没有历史包袱,好上手。他下载了压缩档,花了约两个小时,一口气读完 Git 初代 程式码,发现写得很漂亮,感到由衷佩服。 初版 Git 出现後,Linus 马上又加入了提交(commit)和检视差异(diff)的命令,但 还没有合并(merge)的功能。 Linus 之前没有写过版控软体,但他用过三年的 BitKeeper,在那之前,他更有十年 「版控人体」的经验,他知道自己想要的合并演算法应该长什麽样。但合并的逻辑较为 复杂,Linus 觉得可能使用脚本语言会比较合适,他写道: > 我一直在避免做 merge-tree,因为我希望有其他人来做我所描述的。我不擅长写脚本 > 语言,这东西用 C 语言来写会很冗长,所以没意义。 过了一星期,谁也没上钩。滨野纯刚好正值两个专案的空窗期,有多余时间,於是他用 Perl 把 Linus 想要的东西写出来,发布到邮件列表上。 > 我现在有一个 Perl 脚本利用了 rev-tree、cat-file、还有 merge(从 RCS 来的) > ,又快又脏。 滨野纯大概从他的导师 Paul 那边有学到一些 RCS 的知识,对版控软体略懂。在邮件中 ,他还详细写了大约 30 个测试用例,涵盖各种分支情况。 当时已是深夜一点,而小孩早上七点起床,所以 Linus 平常十点就睡了。但看到滨野纯 的 Perl 脚本,Linus 龙心大悦,忍不住回覆: > 这就是我想要的,「又快又脏」才会让事情有进展。 他热切地继续与滨野纯讨论。 「和 git-pasky 合并 II」这个讨论串原本是 Petr 问 Linus 要不要合并他的版本,後 来离题变成讨论合并演算法,其间 Linus 也向众人解译为什麽 Git 底层不需要处理档 案改名。 从 4 月 14 日半夜的往後 48 小时,滨野纯与 Linus 在该讨论串上通了十几封信。滨 野纯耐心的修改程式码,要做到 Linus 心目中的合并。字里行间不难发现滨野纯是 Linus 的忠实粉丝。例如,滨野纯会引用 Linus 四年前说过的金句「我永远是对」,也 会适度地拍 Linus 的马屁。 在 4 月 16 日半夜,Linus 突然灵机一动,说他想到一个「狡滑的计划」。 > 该死,我的狡滑计划真是好东西。 > 或者也许因为它**太**狡猾了,连我自己都感到困惑。但看起来它确实有效,而且几 > 乎能瞬间完成合并。 Linus 巧妙的重用既有的索引,在其上引入了「阶段」的概念,大幅简化合并演算法的 实作。 看到 Linus 的解法,滨野纯赞叹: > 我很喜欢这个解法,它非常简单、乾净、灵活,而且优雅。这是那种我会心甘情愿地 > 说「天啊!为什麽我之前没想到!!!」的东西。 这意味着滨野纯之前写的 Perl 程式码将沦为白工,但新的解法实在太漂亮,滨野纯心 服口服。 合并演算法只是个开端,之後滨野纯陆续向 Linus 贡献更多修补,逐渐赢得 Linus 的 信任。 Linus 曾说过他不会长期维护 Git,等到时机成熟,他会将 Git 交给别人,然後回去做 他的 Linux Kernel 本业。滨野纯是最明显的人选,Linus 欣赏他写程式的「好品味」 。於是,三个多月後,7 月 26 日,Linus 宣布将 Git 维护人的工作交棒给滨野纯。 滨野纯也贴了一篇公告: > 正如有些人在 Linus 宣布之前似乎已经注意到的那样,kernel.org 上的官方 GIT 仓 > 储现在由我拥有。如同 Linus 在他的讯息中所说,这并不意味着他要离开我们,所以 > 请不要惊慌。 > > 我也要感谢 Twin Sun(我的雇主)和 NEC,他们承诺将支持我以兼职方式开发 GIT。 > 我预计每周会有 8 到 12 小时的工作时间,晚间和周末仍然是我的自由时间。我暂定 > 的计划是将星期三和星期六作为主要的 GIT 工作日。 > > 之前,每当想到一个点子,我就把修补丢邮件列表上,看哪个能被接受,完全依赖上 > 游某个有好品味的人来筛选掉不好的。虽然这样和 Linus 一起工作很有趣,但遗憾的 > 是,我浪费了他很多时间。 > > 从今开始,身为「主仓储的牧羊人」,我会放慢速度,变得更加谨慎。至少目前,你 > 会看到我的修补会像其他人一样,在进入主仓储之前,先在邮件列表上发布。 後来,在滨野纯的带领下,Git 1.0.0 正式在 12 月 21 日释出。19 年後的今天(本文 发布於 2024 年 7 月),滨野纯任职於谷歌,至今他仍是 Git 的维护人。 本文提及 Linus 的次数比滨野纯多,不过 Git 之所以是现在的样子,最大功臣还是默 默耕耘多年的滨野纯和其他开发者。「1% 的天分加上 99% 的努力」或许是老梗,但在 Git 与 Linux Kernel 等成功专案里都是事实。 # GitHub 与 Ruby 人 虽然 Git 在早期引来不少关注,但仍是小众。2006 年 1 月,X Window 团队放弃 CVS ,改用 Git,滨野纯得知後还感到很惊喜,他没料到像 X Window 这像的大专案会愿意 大费周章转换版控系统。 自 BitKeeper 之後,分散式版管系统如雨後春笋般冒出,除了 Monotone 之外,还有 Mercurial、Darcs、Bazaar、Arch、Fossil 等。声势最不容小的是 Mercurial,作者 Matt Mackall 晚了 Git 几天发布它,但功能已比当时的 Git 完整,而且更为使用者友 善,之後更有 Google Code 和 BitBucket 的背书。总之,版控市场犹如战国时代,每 家都占有一席之地。 真正把 Git 推上巅峰、变成主流的是 GitHub。或者根据 Linus 所述,是 Ruby 人,一 群奇怪的人,让 Git 一夕爆红。 2007 年 2 月,Git 1.5 释出,Git 总算变得好用一点。当时在旧金山的 Ruby 聚会口 耳相传着 Git 这个「新」东西。而 GitHub 的共同创办人 Tom Preston-Werner,最早 是从他的同事 Dave Fayram 听到 Git。Tom 认为 Dave 是在 Ruby 社群传播 Git 的 「零号病人」。 尽管在 Ruby 社群中 Git 广受好评,但当时唯一一家 Git 托管服务是 Petr Baudis 的 repo.or.cz,它功能阳春。例如,你的程式码在上面只能公开,没有私人仓储的选项。 Tom 觉得其中大有商机。 2007 年,社群媒体当道,Facebook、YouTube、Twitter 都先红了一波。Tom 萌生了一 个名叫 GitHub 的点子:一个给程式设计师用的社群媒体,一个让程式设计师分享 Git 仓储,交流意见的集散地(hub)。 2007 年 10 月某天,Tom 在一间旧金山的运动酒吧遇到 Chris Wanstrath。他们之前在 Ruby 聚会上认识,但不算熟识。Tom 主动向 Chris 打了招呼,他们聊了起来,Tom 谈 起 GitHub 这个点子。Chris 听到後觉得有趣,就同意加入了。 当时 Tom 和 Chris 都还有正职工作,所以他们每晚和星期六用来开发 GitHub。 Tom 设计介面,并使用一个名为 Grit 的 Ruby 套件来操作 Git 仓储;Chris 则使用 Ruby on Rails 开发网站。 三个月後,他们开始发送邀请给朋友们试用 GitHub。2008 年 2 月,第三个共同创办人 PJ Hyett 加入。4 月 10 日,GitHub 正式开站,它的副标题是 Social Code Hosting。 Ruby 的杀手级应用 Rails,在 GitHub 开站前夕就从 Subversion 移到了 GitHub,这 无疑是帮 Git 在 Ruby 社群注入更大量的强心针。因为当时在写 Ruby 的人,八成都是 在开发 Rails 应用。看到自己赖以为生的框架也用 GitHub ,更多 Ruby 人也欣然跟随 。 # Git 与 GitHub 有冲突的合并 Scott Chacon 不是一个寻常的 Git + Ruby 人,除了写 Ruby 程式外,他还是一个出色 的讲师/写手/传道者。他会录制影片、写文件,教大家怎麽使用 Git。不只如此,他 对 Git 内部运作也有深入研究,曾经写过《Git Internals》这本电子书。 三年来,Git 的「官方」首页一直是 Petr Baudis 在 2005 年架设的 git.or.cz,而 Scott 想设计一个更为新手友善的 Git 首页。2008 年 7 月,他将 git.or.cz 上的内 容整理过後,开设了一个新的首页 git-scm.com,并在 Git 邮件列表上询问 Git 核心 开发成员(尤其是 Petr)的意见。 Git 在 Ruby 社群里虽然已流行了一阵子,但 Git 邮件列表上却鲜少出现 Ruby 人的踪 迹。Git 核心开发成员,大部分是资深的 C 程式设计师,出没在邮件列表;而 Ruby 人 ,大部分是年轻一代的网页开发者,出没在实体聚会、网页式的论譠及 GitHub,搞不好 一辈子都没用过邮件列表。两个族群互不来往,而 Scott 在 Git 邮件列表上那篇关於 git-scm.com 的讯息,是两个族群早期的少数几次接触之一。 另一个让 Git 核心成员伤脑筋的地方是 Tom 未经讨论,擅自用 Erlang 客制 Git Daemon,以满足 GitHub 单方面的需求。这是因为第一,Tom 对 C 语言不熟; 第二,在邮件列表张贴讯息是一件吓人的事,列表上都是比你聪明的人,如果你写的东 西没好好断行,就会看起来像个白痴。这过程实在太缓慢了,Tom 才会自己来。 git-scm.com 上有一个「托管由 GitHub 赞助」的标语,於是就有人质疑 Scott 背後的 动机不单纯,也有人藉此表达 GitHub 用 Git 赚钱,Git 核心开发者却分不到一杯羹的 不满。但整体来说,正面回应居多,最终 git-scm.com 成为 Git 的官方首页, git.or.cz 功成身退。 Tom 是在某次 Ruby 聚会认识 Scott 的,当时 Tom 心想:「这家伙未来不是强大的 盟友,就是危险的对手。」2008 年 10 月,Scott 加入 GitHub,继续他的 Git 传道之 路。他写更多文件,提供顾问服务,到其他公司教大家使用 Git。他还写了一本书 《Pro Git》,为 Git 官方推荐书。GitHub 的大外宣策略骤效了,它成功将 Git 发扬 光大到 Ruby 以外的社群,GitHub 自己是最大受惠者。 2008 年 10 月,谷歌赞助了第一届 GitTogether 会议,Git 和 GitHub 两组人马 20 余人齐聚在谷歌总部山景城。他们放下之前的成见,因为他们很清楚,合作才会让 彼此变得更强大。 ## 後记 无法与 Git 和 GitHub 竞争,BitKeeper 後来被迫退出市场,它的团队在 2016 年将其 程式码开源。这个祖父级的版控软体,曾经是 Git、Mercurial、Monotone 等软体的灵 感来源,如今成了历史文物,供人观赏与研究。被问到有何感想,Larry McVoy 这麽回 应: > 事後诸葛亮最简单了。BitKeeper 的生意经营得很好,我们运营了 18 年,赚的钱足 > 够让我和我的商业夥伴退休,不过还不够让每个人都可以选择退休。 > > 我们曾经有一个类似 github 的服务,现在看来我们应该投入大量资金到那个服务, > 然後开源 BitKeeper。 > > 我只能说,当你已经有一个金鸡母,要割舍它是很困难的。 > > 早知道、早该、早会,我最大的遗憾不是钱,而是 Git 是个糟糕的版本控管系统。它 > 让我抓狂的是,它的模型只是个压缩档伺服器。甚至 Linus 也曾向我承认这个设计很 > 烂。它满足了 Linus 的需求,但他的需求不代表这是这个世界所需要的。 现在,Larry 享受他的退休生活,他平时喜欢和他的孩子们出海钓鱼。 Stack Overflow 在 2022 的调查中,Git 市占率高达 94%,以至於隔年 Stack Overflow 乾脆放弃问大家用什麽版控系统。 历史上从来没有一个版控软体能如此称霸市场,下一个能取代 Git 的会是什麽?不少人 说可能会与 AI 有关,但没人说得准,不过可以确信的是,过程中一定会有一连串的 偶发事件和一群杰出的骇客。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.231.121.115 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1719842445.A.110.html
1F:→ fantasystar: 看完文章才发现是伊亮 07/01 22:23
2F:推 bcew: 谢谢分享,好棒的故事^^ 07/01 22:29
3F:推 v86861062: 推推 07/01 22:46
4F:推 yurucamp: 推 07/01 22:56
5F:推 abc0922001: 看完了,知道好多以前不知道的XD 07/01 23:02
6F:→ abc0922001: 当初 BitKeeper 好像也说会提供 Linus 协助去开发 git 07/01 23:03
7F:推 OldDaiDai: 推 07/01 23:10
8F:推 wulouise: 有够完整,所以Tridgell真的很喜欢逆向工程xd samba也是 07/01 23:12
9F:推 buke: 推 07/01 23:15
10F:推 rtoday: 推 07/01 23:28
11F:推 touurtn: 还以为git是横空出世的概念... 07/01 23:33
12F:推 qazwsx12: 非常精彩!!!只是一口气太长了哈哈 07/01 23:42
13F:推 justptt978: 写的好 07/01 23:52
14F:推 koty6069: 推 07/02 00:13
15F:推 fantasychese: 是不是可以说Git的成功 有一部份是Linus的光环效应 07/02 00:20
16F:→ fantasychese: 不知道有多少本来有机会称霸市场的「周末小专案」 07/02 00:21
17F:→ fantasychese: 因为没有名人加持而被掩埋在历史中 07/02 00:21
18F:推 loxyz: 推 07/02 00:30
19F:推 rdg1231: 好看,Linus喷人好好笑 07/02 00:42
20F:推 ARui: 推推,超级好看! 07/02 01:09
21F:→ ARui: 网页版有很完整的超连结可以点进去看原文考古,超棒的 XDD 07/02 01:09
22F:推 kurtsgm: 推 07/02 01:37
23F:推 justhit666: 推推 07/02 01:49
24F:推 encorek22554: 推,内容整理的很棒! 07/02 02:21
25F:推 DrizztMon: 真的好文 07/02 03:11
26F:推 siriusu: 已拜读,感谢分享! 07/02 03:53
27F:推 steve8625: 推 07/02 07:01
28F:推 taikobo: 有看有推 07/02 07:36
29F:推 jimjim951357: 推 07/02 07:43
30F:推 EasonLiu: 推推 07/02 07:53
31F:推 keepxha: 推 07/02 07:54
32F:推 HelloPPT: 推 07/02 08:16
33F:推 chandlerkc: 好文 07/02 08:40
34F:推 mikukonn: 推 07/02 08:43
35F:推 px172: 推 07/02 08:53
36F:推 ian90911: 推好文 07/02 09:00
37F:推 Bencrie: 推 07/02 09:08
38F:推 leokidd1976: 推 07/02 09:23
39F:推 sssyoyo: 软体考古系列 先推再看 07/02 09:26
40F:推 whyhsu: 推 07/02 09:30
41F:推 descent: 感谢分享 07/02 09:40
42F:推 chihlee5566: 林姓商人 07/02 09:44
43F:推 germun: 超完整推 07/02 10:21
44F:推 applewarm: 推讲故事 07/02 10:23
45F:推 kaitokid1214: 好文 07/02 10:26
46F:推 wistful96: 推 07/02 10:28
47F:推 zerofinal: 推 07/02 10:28
48F:推 abc0922001: Linus 在 Google 演讲 git 的也很有趣 Youtube 有 07/02 10:29
49F:推 karst10607: 非常有趣的故事,感谢分享 07/02 10:46
50F:嘘 B0988698088: 太长 07/02 11:01
51F:推 a826451115: 推好文 07/02 12:04
52F:推 papple23g: 推 07/02 12:11
53F:推 y2468101216: 推 07/02 12:25
54F:推 kai2573: 推 07/02 13:12
55F:推 duck10704: 先推再看 07/02 13:17
56F:推 wei115: git处理纯文字很强 但其他格式就没什麽能力惹 07/02 13:18
57F:推 zyxx: 推 07/02 13:23
58F:推 srwhite: 赞赞 07/02 13:37
59F:推 VL1003: 优文 07/02 13:55
60F:推 CaptPlanet: 推 07/02 14:20
61F:推 joewang85: 推好文 07/02 14:31
62F:推 Jonny5: 推 我竟然看完了 07/02 14:54
63F:推 timmerix: 推推 07/02 15:42
64F:推 psychoPass16: 推 !当小说看 07/02 15:50
65F:推 peter1111: 推 07/02 15:50
66F:推 summerleaves: 优文 07/02 15:54
67F:推 justty32: 推 07/02 16:32
68F:推 tsukiyoK: 推 非常精彩 07/02 16:36
69F:推 lorne5: 推 07/02 17:13
70F:推 Ftso: 推 故事很有趣! 希望可以看到更多精彩介绍! 07/02 17:17
71F:推 unicornGL: 太好看,希望未来多一些,嘘的有够可悲 07/02 17:22
72F:推 wizozd84070: 推 07/02 17:42
73F:推 kyrie77: 这篇超屌… 07/02 17:50
74F:推 shadow0326: 推 07/02 17:54
75F:推 Everbo: push 07/02 18:26
76F:推 OldTjikko: 推 07/02 18:26
77F:推 nksp: 推 07/02 19:05
78F:推 peteryu168: 纯推 07/02 19:14
79F:推 ASFCommander: 推推 07/02 19:28
80F:推 rickphyman42: 推爆 长知识了 07/02 20:17
81F:推 st87253: Push 07/02 20:31
82F:推 andy9595995: 看完推,真有趣 07/02 20:52
83F:推 joshua25: 你历史系!!! 赞 07/02 21:04
84F:推 nh60211as: 推 07/02 21:17
85F:推 ELivan: 推 07/02 22:03
86F:推 easters14: 推 07/02 22:12
87F:推 jlhc: 推推 07/02 22:34
88F:推 vi000246: 真是精彩 07/02 23:48
89F:推 windclock: 我居然看完了 07/02 23:53
90F:推 michael0543: 推! 07/03 00:30
91F:推 lspss93161: 这篇值得推 07/03 00:59
92F:推 Burwei: 推 好好看 07/03 01:00
93F:推 k12795: 豪堪! 07/03 02:35
94F:推 chao0210: 赞 07/03 07:51
95F:推 doggy0704: 好看的文很长也看得完 07/03 08:47
96F:推 allnun: 推! 07/03 08:54
97F:推 sokamin: 推 07/03 09:40
98F:推 TonyQ: 推 07/03 10:35
99F:推 a731977: 推 07/03 10:39
100F:推 lynx: 推 07/03 11:09
101F:推 GTX9080: 好看!感谢分享 07/03 11:34
102F:推 mozume: 推,精采,感谢分享大神们的世界 07/03 12:31
103F:推 jack42107: 好好看 推推 07/03 13:28
104F:推 nashmvp: 推 07/03 13:47
105F:推 jyunwei: 赞 07/03 14:06
106F:推 e811222c: 推推 07/03 14:29
107F:推 kelvin0004: 感谢分享 有趣的历史 07/03 14:31
108F:推 APTON: 好看!! 07/03 14:53
109F:推 TohmaMiyuki: 推 07/03 14:57
110F:推 oherman: 这些软体大师性格也满cute 07/03 16:20
111F:推 sniper2824: 推 07/03 16:21
112F:推 yelredorange: 推推 07/03 16:34
113F:推 wangm4a1: 推 07/03 17:09
114F:推 akasan: 推 07/03 18:49
115F:推 yalanin: 好精彩 07/03 19:08
116F:推 pumapupa: 长知识推 07/03 19:28
117F:推 ntuee1803: 推 07/03 19:45
118F:推 nek0t1m: 推 07/03 19:46
119F:推 atteleitus: 推推 07/03 20:28
120F:推 hsia0403: 谢谢整理 07/03 22:03
121F:推 lukelove: !? 文学的出路:软体史 07/03 23:24
122F:推 longlyeagle: nice 07/03 23:32
123F:推 ms0529876: 推 07/03 23:56
124F:推 jerryway: 推 很有趣 07/04 08:29
125F:推 mcmj5566: 推推 07/04 08:46
126F:推 Tokukenis: 推 07/04 09:46
127F:推 lorderic: 有看有推 07/04 10:46
128F:推 MICHAELorz: 推 07/04 11:23
129F:推 Truer: 很有趣,推 07/04 12:50
130F:推 hotahaha: 好长 推 07/04 14:47
131F:推 leviliang: 乾 也太好看了吧! 07/04 15:16
132F:推 riddick9527: 推考古 07/04 15:22
133F:推 freedls: 有趣!! 07/04 16:58
134F:推 toegazer: 好猛 07/04 17:47
135F:推 Rulerchen: 推 07/04 18:28
136F:推 jay123peter: 推 07/04 19:08
137F:推 c2413576809: 推 07/04 20:00
138F:推 gclass: 推 07/04 20:29
139F:推 kasimEnix: 感谢分享,这些故事都好有趣 07/04 21:05
140F:→ uncle925: 推好文 07/04 21:34
141F:推 jessie83: 推 07/04 23:41
142F:推 john721: 还没看完先推一个 07/05 00:11
143F:推 e12518166339: 推 07/05 01:30
144F:推 Luos: SVN还真够老 07/05 01:35
145F:推 jay123peter: 推 07/05 02:46
146F:推 developers: Scooter 还蛮好笑的XD 07/05 05:33
147F:推 nayeonmywife: 推 07/05 09:30
148F:推 internetms52: 推 07/05 16:03
149F:推 alsk1566: 感谢分享,超有趣 07/05 18:54
150F:推 six93250: 推 07/05 21:16
151F:推 cloudpsp: 推推很有趣! 07/06 01:45
152F:推 ponsheng: 推 长知识 07/06 09:22
153F:推 jay16814: 推推 07/06 10:54
154F:推 haoyuan3151: 推 07/06 10:58
155F:推 leonidass: 推 07/06 12:25
156F:推 fei6409: 推推 另外 Scott 的 Git talks 也很有趣 07/06 12:42
157F:→ fei6409: 例如 https://youtu.be/aolI_Rz0ZqY 07/06 12:43
158F:推 ayugioh2003: 推推 07/06 13:01
159F:推 mazdathree: 您的文笔真好 好有趣 有没有考虑出书啊 07/06 13:45
160F:推 itsdelovely: 推推 07/06 14:16
161F:推 william8403: 推 有趣 07/06 17:24
162F:推 Ekmund: 推 原来2005到现在已经19年了啊........... 07/06 19:54
163F:推 EEEEEEEnd14: 推 很有趣 07/06 20:08
164F:推 d8888: 推好文 07/06 20:47
165F:推 inte629l: 推 好有趣 07/07 07:56
166F:推 RoyalA: 优质文章 大推 07/07 11:38
167F:推 kkk99923: 超精彩 这个量看得好爽 07/07 20:37
168F:推 unmolk: 感谢分享 07/07 21:25
169F:推 MangoTW: 精彩的来龙去脉 07/08 02:06
170F:推 obarisk: 推 07/08 08:11
171F:推 spath: 好文推推 07/08 09:18
172F:推 ho83leo: 真屌... 推 07/08 10:21
173F:推 wxywxywxy: 不知不觉看完了 写得真好 07/08 12:29
174F:推 sck921: 推 07/08 13:56
175F:推 l145678p: 推推 07/08 16:48
176F:推 mikeqoo1: 推推 资讯历史好好玩 07/08 19:39
177F:推 errr2333: 推 07/08 21:29
178F:推 jj2564: 推,本来该睡觉了结果不小心看到... 07/08 23:31
179F:推 Nt9ii45: 推 07/09 02:20
180F:推 ddkkz2003: 推 07/09 11:22
181F:推 DarkNT: 推 07/09 16:04
182F:推 ch12789: 推推 07/09 21:34
183F:推 ericthree: 推 大神的故事真好看 07/10 08:07
184F:推 fallen01: Linus真的屌 07/10 12:03
185F:推 infernodimon: 长知识 推 07/10 22:00
186F:推 kakahikari: 推 07/11 00:12
187F:推 wk415937: 推 07/11 12:41
188F:推 flysonics: 推 07/11 12:48
189F:推 chan15: 精彩 07/11 16:55
190F:推 math79: 推 ! 07/12 00:17
191F:推 kenwufederer: 推 07/12 12:38
192F:推 oceanmygod: 有趣 07/13 17:37
193F:推 meteorboy: 太精彩了! 07/15 12:17
194F:推 edwardhsu: 强 07/15 19:07
195F:推 ptt0211: 推 07/16 15:48
196F:推 genic: 推 07/16 21:06
197F:推 shiwa: 推 07/17 07:37
198F:推 tomroy: 酷! 07/17 15:55
199F:推 fullout: 推+收藏,有英文原文太棒惹 07/18 18:54
200F:推 ming0071: 故事超有趣 推! 07/19 17:27
201F:推 s860134: 精采 07/19 20:17
202F:推 PoiViww: 好好看 07/20 03:19
203F:推 velaro: Git 真的糟糕…..好险现在换公司不用再想merge conflict 07/21 03:54
204F:→ velaro: 了 07/21 03:54
205F:推 JZGY: 叙事流畅增广见闻,大推!! 07/24 11:22
206F:推 fishxd1096: 推 好看 07/27 04:23
207F:推 LeaderH: 好看 07/27 23:34
208F:推 silveryiris: 推 08/10 15:01
209F:推 bj78947: 推 09/08 02:07







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Boy-Girl站内搜寻

TOP