下一章 上一章 目录 设置
3、第三章?【Merge Conflict】
校赛平 ...
-
校赛平台上线当天,崩了。
准确来说,是评测姬在第八分钟进入死循环,CPU 占用率飙到 100%,老师的电话比栈溢出还快地砸下来:“祁雁行、才子涵,五分钟内给我现场热修!”
我和祁雁行冲到机房时,屏幕正一片血红。
日志像失控的加特林,疯狂刷屏:Segmentation Fault、std::bad_alloc、std::map iterator invalidated。
我头皮发麻:“昨晚最后一组数据不是 AC 吗?”
祁雁行没回答,直接切到 gdb,十几行回溯之后,光标停在一行代码:
auto it = pool.find(key);
pool.erase(it++); // UB: erase 后 it 已失效
我愣住。这行代码是他写的,但 review 表上签的是我名字。
也就是说,昨晚我亲手放过了这个低级却致命的 bug。
“我……”嗓子发干,“对不起。”
祁雁行的手指悬在键盘上,指节泛白。他没看我,声音却比平时更低:“先止血,再问责。”
止血过程只有 37 秒:
他 rollback 到上一个 tag,我 hot-patch 掉有问题的迭代器,重启服务。
CPU 曲线像被拔掉电源的风扇,瞬间归零。
机房安静得能听见荧光灯的电流声。
老师推门进来,目光扫过屏幕,又扫过我们,最终叹了口气:“事故报告晚上交,先去吃饭。”
脚步声远去后,祁雁行坐在椅子上,手背青筋隐现。
我知道他在压抑情绪——对别人是 0 和 1,对他自己却是负无穷。
“祁雁行。”
“……”
“你要骂就骂,别憋着。”
他终于抬头,眼底是罕见的血丝:“我生气的不是你漏掉 bug,而是——”
话到一半戛然而止,像被强行截断的 socket。
我走近一步:“而是什么?”
他抿唇,像在把某个危险关键词压回编译期。
最终,他吐出一句极轻的:“而是我没在第一时间想到你会自责。”
那一瞬,心脏像被 soft link 击中——软连接,硬疼。
我拖过旁边的椅子坐下,和他并肩,像两个等待复审的 PR。
“我也有话。”
“说。”
“我 review 的时候确实分心了。”
“分什么心?”
“分心去想——”我舔了舔嘴唇,“如果以后我们不在一个 repo,怎么办?”
祁雁行的睫毛颤了一下,像被风吹乱的指令指针。
良久,他开口,声音低到只有两人能听见:“那就 fork。”
我苦笑:“fork 之后呢?两条分支越走越远,merge 不回来。”
他侧头看我,目光幽深:“不会。”
“凭什么?”
“凭我永远不会 close 你的 PR。”
空气突然变得粘稠。
我听见自己心跳在耳膜里打鼓,咚咚,咚咚。
祁雁行先别开眼,站起身:“走,去吃饭。”
“我想吃辣的。”
“胃不要了?”
“Bug 压惊。”
他几不可闻地叹气,却还是把外套丢给我:“敢点特辣就扣你 commit 权限。”
傍晚的校园广播放着《晴天》。
我们一前一后穿过操场,影子被夕阳拉得很长。
我踩着他的影子,小声哼歌。
祁雁行忽然停住,我没刹住车,额头撞在他肩胛骨上。
“喂——”
“才子涵。”他转身,声音被风吹得有点抖,“下次再遇到 conflict,不要一个人改。”
“那要怎样?”
“叫我。”
他伸出手,掌心向上,纹路清晰得像电路板。
我愣了两秒,把指尖放上去。
祁雁行扣住我的手,十指交错,像把两条分支强行 merge 成一个哈希值。
“这样。”他说。
广播恰好放到副歌:
“好不容易又能再多爱一天。”
我想,原来 0 和 1 之间,也有中间态——
叫做“我们”。
----
事故报告最终只写了一句话:
root cause: iterator invalidated by concurrent emotion. fix: hand-in-hand review.
老师回了一个“?”
我偷笑,把报告丢进回收站,再新建一个文件,命名为:
merge_strategy.md
正文只有一行:
git config --global user.name "qi&cai"