前言
20xx年x月x日。
有这么一个公司项目组。
负责人制订了流程,设计了模板。
而他的员工们,全都不作为,想着老板会兜底。
最终,项目彻底崩溃。负责人扛下了所有锅。
他在绝望地嘶吼着,喊着"我有事",然而自始至终都没有人听见。
别觉得上述例子沉痛过了头,那是因为你不是那个抗伤的。这种例子,随便哪个场合都有可能发生,不论是竞赛战队、企业工作,还是科学研究、课程项目,都会有。
第一部分:什么是CI/CD(给没看过往期的补个课)
一句话版
CI/CD,全称为持续集成与持续交付系统。
门禁系统 :不刷卡不让进,不达标不让合。
自动流水线:你只管提交,测试、编译、部署它自己跑。
技术人话版
CI(持续集成/Continuous Integration) :你每次提交代码,系统自动编译、自动测试、自动校验,不通过就直接打回去,不用收拾烂摊子了。
CD(持续交付/Continuous Delivery) :测试通过后,系统自动部署到目标环境,不用你手动部署、手动重启、手动改配置。
合起来,CI/CD就是一套代码从提交到上线全自动、可拦截、可追溯的流水线系统。
没有CI/CD的系统
- 代码质量靠人盯:谁认真谁不认真,全凭自觉。
- 提交记录靠手查:出了问题翻聊天记录,翻不出来就扯皮。
- 上线部署靠手动:传包、重启、改配置,一步错步步错。
- 规范执行靠喊话:你说"别force push",他偏force push,你除了骂人没别的办法。
有CI/CD的系统
- 代码质量靠系统拦:测试不通过,CI直接拒绝合并,自动近防炮,你值得信赖。
- 提交记录靠系统存:谁在何时何地改了什么,git log里全有,之前第12期说过,详情可从合集跳转。
- 上线部署靠系统跑:你只管提交,剩下的它自己来。自动化流水线,编译部署一条龙。
- 规范执行靠系统强制:你force push?CI直接拦截。你想绕过?由不得你。
没有CI/CD的团队,像没有交通信号灯的路口:谁技术好谁先过,谁不要命谁先过,谁脸皮厚谁先过。看着好像也能通车,但早晚撞上。横冲直撞的,那叫自甘风险,规矩办事但出事的,那叫倒霉蛋。
有CI/CD的团队,像装了红绿灯和电子警察的路口:红灯一亮,谁都得停。你闯红灯,探头一拍,𡂿,6分没了。不需要交警站在路口骂人,系统替你管。(注:探头,上海话特指道路违章监控摄像)
第二部分:CI/CD的定位作用
CI/CD不能替代人类的进攻性价值,但能完美适配人类的防御性需求。
人类的进攻性价值 :设计架构、定义接口、判断优先级、做技术选型、写核心逻辑。
人类的防御性需求:不让乱提交、不让跳过测试、不让force push、不让封仓后动手。
CI/CD管的是后者。它不替你"想 ",它替你"拦"。
作用1:拦截内奸
CI的第一作用不是"帮你做事",是"不让内奸乱来"。
- 测试没过?不准合并。
- 代码规范不过?不准合并。
- 时间过了封仓节点?不准提交。
- 你没权限?动都别想动。403伺候。
CI不是你的助手,CI是门卫。 你符合标准,它放你过。你不符合标准,它拦你。它不跟你讲情面,不跟你商量,不跟你"这次算了"。🎶开封有个包青天~铁面无私辨忠奸~
拦截的本质是:把"人盯人"变成"系统盯人"。
作用2:巡天雷达
CI的第二大作用,便是信息归档。
- 谁提了PR?
- PR有没有经过实践检验?
- 如果没有,这个PR在哪一步挂掉的?
这些可全在git log里躺着。甚至有些强大的CI能够邮件通知肇事者。
你不要以为你出了事情没人知道。老大哥可在盯着你呢。
巡天雷达扫没扫不重要,重要的是你家内奸相信它会扫。
CI的防守反击能力,比你想的要强得多。
作用3:绝对壁垒
CI的第三大作用,便是保证内奸的一切不合规操作失效。
包括但不限于:"我没看到"、"通融一下"、"就这一次"、"咕咕咕"等一系列熟人社会卖萌撒泼操作。人会心软,CI不会。
- 你想force push?CI说不行。
- 你想跳过测试?CI说不行。
- 你想在封仓后提交?CI说不行。
- 你想"就这一次"?CI说不行。
无数个案例表明这些所谓的"通融"会导致放纵和事故。故而,工程环境,要的是一个不听任何人多解释的仲裁系统。
作用4:圣洁守护
CI对于内奸,是限制。对于忠臣,则是最有力的保障之一。
- 你的代码,不会被别人玷污。
- 你的数据,不会被别人篡改。
- 你的东西,不会被别人砸烂。
忠臣们无疑是不想被内奸折磨的。谁都不想自己的功劳被一个没有规矩的人砸烂。
作用5:系统法制
费孝通先生的《乡土中国》说过,城市,是一个法制体系。
没有CI :规矩靠话事人喊,话事人一走,规矩就散。
有CI:规矩写在配置里,谁走都不影响。
CI把"某个人在盯着"变成了"系统在盯着"。 你不需要一个"暴君"来管团队,你需要一套"法律"来管团队。CI就是那套法律。它能够强制落实,不讲人情。
治理的本质是:把"人在,规矩在 "变成"系统在,规矩在 "。
你不需要一个人格化的"暴君"。你需要一套非人格化的"制度"。
CI就是那个制度。它不生气,不偏心,不"这次算了"。它只按写好的规则执行。
第三部分:四国大战(方式对比)
没错。这次实验规模升级了,以往是只有萌新vs老鸟的单变量思维对比,今天,升级到双变量。定义如下:
萌新思维 :巨婴逻辑,做事不考虑其他人,只想着自己,且出了问题就想赖。
老鸟思维:职场逻辑,料事长远,如无必要,绝不破坏流程。
仍然是以企业github项目为例。
A组:全队萌新/无CI
首先最重要的是什么?萌新不一定会考虑瞎搞事的后果。
前面第12篇已经骂过force push的后果,一推上去,人家的成果白费。人家想骂你,但找不到任何一个合法骂你的窗口。
最终,内部扯皮是必然的,团队崩溃也是必然的。
核心:没有强制规则,就没有问罪的流程。
B组:全队老鸟/无CI
一般而言,老鸟不像A组萌新,能够考虑到别人的成果。但这个组合的问题在哪?
还得靠人盯人完成控制。
但凡话事人请假几天,整个队伍就会六神无主,最终可能在虚无中崩掉。
核心:人在规矩在,人走了,规矩就没了。
C组:全队萌新/有CI
和A组本质的区别就是:用系统封锁这些萌新可能的作妖路径。
萌新巨婴思维在职场,说难听点,那就是公敌。他们不接受控制?他们要自由?那就别在企业干工程岗。这不是给他们自由的温柔乡。
钱学森钱老在《工程控制论》说过:控制论的基本问题,其关键,就在于存在各种不确定因素。
我们则可以通过限制变量参数,将结果约束到可控制范围之内。
核心:愿意学的萌新,很好,你已经迈出了成为老鸟的第一步;不愿意学的......这个环境容不得你。
D组:全队老鸟/有CI
如果说C组的CI对交付是雪中送炭,D组则是锦上添花。
哪怕话事人走了,交付流程变了,老鸟看一眼CI就知道该怎么做。
老鸟能克隆仓库,自然可以看CI代码。看得见≠改得了。
老鸟本来就知道该守规范,CI一加,疲劳驾驶风险也大幅度降低。
最终,这一组是能够直接自动化运行的。
核心:老鸟保平时,CI保意外,整个团队滴水不漏。
四组对比总表
| 组别 | 人员构成 | CI状态 | 靠什么管 | 话事人走了会怎样 | CI的作用 | 核心结论 |
|---|---|---|---|---|---|---|
| A | 全队萌新 | 无CI | 无 | 必然崩 | 无 | 没有强制规则,就没有问罪的流程 |
| B | 全队老鸟 | 无CI | 人盯人 | 可能崩 | 无 | 人在规矩在,人走了规矩就没了 |
| C | 全队萌新 | 有CI | 系统强制 | 规矩还在 | 封锁作妖路径 | 愿意学的迈出第一步,不愿意的容不下你 |
| D | 全队老鸟 | 有CI | 系统+人 | 规矩不变 | 自动化运行 | 老鸟保平时,CI保意外,滴水不漏 |
第四部分:四国大战扯皮日常(吐槽还是有)
这次由于是双变量实验,吐槽不是萌新对老鸟这么简单,而是BC可能骂A,D可能骂B的情况。
场景1:A组萌新被D组CI驳回
A:我本地跑得好好的,怎么CI给我驳回了?肯定是CI有问题。
D(冷笑):你本地跑得好好的?你本地连的是localhost,CI连的是测试环境。你当CI是你家路由器啊?
A:那我把URL改成测试环境的不就行了?
D:你改URL,你测试跑了吗?你字段对齐了吗?你连git commit message都写的是'fix',CI不驳你驳谁?
A:那我不干了行不行?
D:行啊,门在那边。CI不拦你,门也不拦你。你这是不能胜任工作,我们证据摆着,你哪怕仲裁也没有N。我们只要熬过30天就能把你合法辞退。哦等会,忘了你试用期,根据《劳动合同法》39条,你连那30天机会都没有,直接卷铺盖吧,不送,老板等会会把纸质版辞退通知书送到你家。😃
《劳动合同法》相关法条原文
第三十九条 用人单位单方即时解除劳动合同
劳动者有下列情形之一的,用人单位可以解除劳动合同:
(一)在试用期间被证明不符合录用条件的;
(二)严重违反用人单位的规章制度的;
(三)严重失职,营私舞弊,给用人单位造成重大损害的;
(四)劳动者同时与其他用人单位建立劳动关系,对完成本单位的工作任务造成严重影响,或者经用人单位提出,拒不改正的;
(五)因本法第二十六条第一款第一项规定的情形致使劳动合同无效的;
(六)被依法追究刑事责任的。
场景2:B组和D组论CI/CD
B:CI/CD?这玩意配置好像很麻烦欸。这玩意我20年都没用过。我没违反过规范,也没出过事故。
D:哦?20年?你的运气确实挺好。
D:不过这东西对你也有好处。如果你作为一个带团队的指挥,出了什么意外情况缺了席,只要CI在,这玩意能够护你周全。
B:怎么说?这玩意一次部署就能够替我自动拦截吗?
D:没错。培训学习成本是一次性的。收益是长期计算的。这玩意对你,稳赚不赔,都是守规矩的人,我不用替你计算。
场景3:A组和B组论秩序
A:为什么非得讲秩序?!我要自由!我要创造!
B:......
B:老板我想申请调组。
场景4:C组的逆袭
A:C,你到底是怎么转正的,我又被开了!!
C:两个字,规矩。
C:四个字,建设规矩。
C:理解规矩,利用规矩,建设规矩。我已经不是那种巨婴了,我破茧重生了。
第五部分:一个相对完善的CI系统分工
(以github action为例)
模块1:时间铡刀模块
拦截类型 :封仓节点之后的任何提交。注意:该模块的判定条件是模块实际运行时间 。部分老板可能会把时间铡刀模块放到最后,甚至可能双铡刀,专治"卡点主义",工程上这种战术叫做"延迟门禁策略"。你要是不提早交卷还合不进去。就像赶飞机,有机票也没用,必须提早到,拿到你的登机牌。
场景:某科研竞赛封仓前5分钟,萌新想起来"模型还有个参数没改",直接在封仓后提交。封仓文件被覆盖,论文数据对不上。
实现例:
yaml
on:
push:
branches: [main]
jobs:
time_gate:
runs-on: ubuntu-latest
steps:
- name: Check deadline
run: |
DEADLINE="2026-09-20T20:00:00Z"
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
if [[ "$NOW" > "$DEADLINE" ]]; then
echo "::error::封仓时间已过,拒绝合并"
exit 1
fi
核心逻辑 :时间不是"建议",是硬边界 。封仓时间一到,CI直接拦掉 。你想"再改一下",系统不让。特别是"延迟门禁"打法,吃过一次亏你就不想吃第二次。
模块2:越权控制模块
拦截类型 :跨目录force push,尤其是涉及别人模块的操作。
场景:萌新要改自己的前端组件,顺手把后端接口目录也force push了。后端老鸟写了三天的接口,没了。
实现例:用 GitHub Actions 配合 paths 过滤 + CODEOWNERS 文件。每个目录有对应的 owner,你改别人的目录,CI 直接拒绝合并。
on:
pull_request:
paths:
- 'backend/**'
jobs:
check_ownership:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check if author owns the changed path
run: |
AUTHOR=${{ github.actor }}
CHANGED=$(git diff --name-only origin/main...HEAD)
# 检查 changed 文件是否在作者负责的目录下
# 不是 → 拒绝
核心逻辑 :权限不是"看你自觉",是按文件夹锁死。你只能动你的模块,动别人的,CI直接拒绝,不用别人出手。
模块3:自动编译模块
拦截类型 :本地能跑、CI跑不起来的代码。
场景 :萌新本地跑得好好的,CI里连编译都过不了。因为本地有缓存,CI是干净环境。专治"本地跑得好好的"主义。
实现例 :
以Java程序项目为例。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
- name: Build
run: ./gradlew build
核心逻辑:本地是"你的环境",CI是"目标环境"。你在本地跑通不算数,CI跑通才算数。
模块4:成品校验模块
拦截类型 :测试没通过、跳过测试、假装测过。报告没写或者根本来不及写。
场景:萌新说"我测过了",CI一跑,测试用例全挂。他说"我本地测过的",但他本地根本没跑测试。
实现例 :
以Java程序项目为例。
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: ./gradlew test
- name: Upload test report
if: always()
uses: actions/upload-artifact@v4
with:
name: test-report
path: build/reports/tests/
核心逻辑:测没测过,不是靠嘴说,是靠CI记录。CI里没有测试通过记录,就不给合并。
模块5a-科研型:追根溯源模块
拦截类型 :数据来源不明、模型版本不匹配、结果无法复现。
场景:数模竞赛某团队,建模手改了模型,代码手没改代码。论文里的数据对不上,没人知道哪个是"最终版"。
实现例:
jobs:
data_provenance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify data hash
run: |
# 检查数据文件的hash是否匹配
# 检查模型版本是否与数据版本一致
# 不一致 → 拒绝
- name: Reproduce results
run: |
# 用当前代码跑一遍,看结果是否与提交的论文数据一致
# 不一致 → 拒绝
核心逻辑:数据来源可追溯,模型版本可对应。你改了模型,数据没跟着改,CI直接拒绝。
模块5b-项目型:契约对应模块
拦截类型 :接口字段不对齐、类型不匹配、错误码不一致。
场景 :后端说"返回 下划线user_name ",前端写的是 驼峰userName。联调的时候,前端崩了,后端说"我按文档写的"。
实现例:
jobs:
contract_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate OpenAPI spec
run: |
# 用 OpenAPI 规范校验接口定义
# 检查前端代码里的字段名是否与规范一致
# 不一致 → 拒绝
核心逻辑:接口字段不是"口头约定",是CI里的强制校验。你传 userName,文档要求 user_name,CI直接拒绝。
模块6:异地容灾模块
拦截类型 :主分支被污染,缓存分支还在。
场景:萌新直接往 main 分支 push,CI 没通过也硬上。主分支乱了,没人敢回滚。
实现例:
jobs:
protect_main:
runs-on: ubuntu-latest
steps:
- name: Protect main branch
run: |
# 检查 main 分支的 CI 状态
# 如果 CI 未通过,禁止合并
# 主分支和缓存分支物理隔离
核心逻辑:主分支和缓存分支物理隔离。CI不通过,主分支进不去。你想"硬上",系统不给你这个选项,403是常态。最安全的方式就是没人能改主分支。
模块7:行为记录模块
拦截类型 :不守规矩的人。
场景:萌新force push,覆盖了队友的代码。队友问"谁改的",萌新说"不是我"。
实现例:
jobs:
audit_log:
runs-on: ubuntu-latest
steps:
- name: Log all actions
run: |
# 记录每次提交的作者、时间、文件、CI状态
# 记录每次驳回的原因
# 记录每次绕过尝试
# 写入审计日志
核心逻辑:CI不通过,git记录谁、何时、何地、干了什么。剩下的事,就是按规范流程问罪。你不是"在骂人",你是在"在留证据"。
第六部分:老鸟内心精选(CI维权版)
场景1:A组萌新被CI驳回,找老鸟哭诉
A组萌新:"CI驳回了我的提交,这系统是不是针对我?"
D组老鸟内心 :
针对你?咱家CI又没有根据人来拦截的任务,都是根据部门统一拦截的,它驳回咱们的可能原因全集,是一致的。CI连你是谁都不知道。它只认代码、只认规则、只认时间。你觉得它针对你?你先看看你的commit message写的是什么------"fix"。fix什么?哪里fix?怎么fix?你写遗嘱也这么随便吗?
你说"本地跑得好好的"?你本地连的是localhost,CI连的是测试环境。你当CI是你家路由器啊?
你觉得CI针对你?CI要针对你,你连提交的机会都没有。它现在只是驳回你,已经够客气了。你要是再force push,那就不是驳回,是403。你那时候连权限都没了。
场景2:B组老鸟质疑CI的必要性
B组老鸟:"我二十年没出过事,CI这玩意有必要吗?"
D组老鸟内心 :
二十年没出过事,是你的运气,不是你的本事。你没出过事,是因为你没遇到过一个force push的队友。你遇到了,你就知道CI近防炮重要了。
你说"我自觉"?自觉是消耗品。你今天自觉,明天自觉,后天累了呢?请假了呢?离职了呢?你是个活生生的人,不是机器。你我都无法保证自己到退休都不会出错,甚至你我都无法保证能不能撑过35。
你说"CI太死板"?CI死板,是因为人太灵活。人灵活到force push,灵活到跳过测试,灵活到封仓后提交。CI不是死板,是它不跟你讲情面。
你说"我用不着"?你用不着,但你带的团队用不着吗?你请假了,你的团队怎么办?你离职了,你的规矩怎么办?
CI不是给你用的,是给你不在的时候用的。
场景3:C组萌新被CI驳回三次后破防
C组萌新:"我都改了三遍了,CI还驳我,我不干了!"
老鸟内心 :
你不干了?你改了三遍就破防,我改了三十遍都没说话。你改了三遍,是因为你没看日志。你看了日志,就知道错在哪。你没看日志,改一百遍也是白改。日志不是废话,是办案线索,是警察抓小偷的证据。
CI驳你,不是"针对你",是"告诉你错在哪"。你被驳回了三次,说明你有三个地方不对。你改一个地方,重交一次。你改完了,就过了。
你现在说"不干了"?可以。门在那边。但你不是"主动辞职",你是"被系统淘汰"。CI记录摆在那里,你仲裁也赢不了。你不是"不想干",你是"干不了"。
场景4:D组老鸟被问"CI会不会太严"
C组新人:"D哥,CI会不会太严了?一点小错都不让过。"
D组老鸟内心 :
小错?你说的小错,是commit message写"fix",是URL写localhost,是测试跳过没跑,是force push覆盖别人的劳动成果。这些在你眼里是"小错",在工程里叫"事故前兆"。不是CI太严,是你还没在职场待久。我脾气差,但我不会搞死别人。你能思考CI的重要性,这部分已经强过部分萌新了。
你觉得"一点小错都不让过"是严?那我问你:你开车不系安全带,算不算"小错"?你闯红灯,算不算"小错"?你觉得是"小错",因为你没出过事。出了事,就不是"小错"了,是"重大事故"。
CI不是"严",是不给你"这次算了"的机会 。你不守规矩,它不跟你商量。你守规矩,它放你过。你守规矩还出事,那是倒霉。你不守规矩出事,那是活该。
场景5:A组萌新被辞退后,回头找老鸟
A组萌新:"我被开了。我就想问一句,我到底错在哪?"
老鸟内心 :
你错在哪?你错在force push覆盖别人代码的时候,没想过别人。你错在commit message写"fix"的时候,没想过读log的人。你错在跳过测试的时候,没想过用户。你错在封仓后提交的时候,没想过全队。
你不是"不知道",你是"不想知道"。你被CI驳回的时候,你说"CI针对我"。你被辞退的时候,你说"我到底错在哪"。你到现在还在问"我错在哪",说明你根本没意识到自己错了。
你不是"被开了",你是"被系统淘汰了"。CI记录摆在那里,你仲裁也赢不了。你不是"运气不好",你是"不适合工程环境"。
CI不骂人,CI只记录。
老鸟不骂人,老鸟只翻译。
翻译的结果,就是A组的辞退通知书。
第七部分:总结
CI/CD 特点总表
| 维度 | CI/CD 能做什么 | CI/CD 不能做什么 | 本质 |
|---|---|---|---|
| 拦截 | 不达标不让合并,403伺候 | 防不了偷懒的(磨洋工、拖延、假装在忙) | 只管行为,不管态度 |
| 追溯 | 记录谁在何时何地干了什么 | 做不到后续追责(追不追责是管理层的事) | 只管记录,不管判决 |
| 强制 | 剥夺你的"决定权",不由你决定 | 防不住黑客攻击(外部入侵是另一套系统) | 只管内部,不管外部 |
| 保护 | 让守规矩的人不"自甘风险" | 防不住"家里养不熟的猫"(内鬼防不胜防) | 只管规则,不管人心 |
| 治理 | 把"人治"变成"法治" | 不能替代人类的进攻性价值(设计架构、定接口、做决策) | 只管防御,不管进攻 |
| 威慑 | 巡天雷达,内奸相信它会扫 | 威慑力取决于内奸是否"相信" | 只管心理,不管事实 |
| 时间 | 时间铡刀,封仓后不准提交 | 防不了"提前交卷但交的是烂卷" | 只管时间,不管质量 |
| 权限 | 越权封锁,你只能动你的 | 防不了"有权限但乱用权限" | 只管边界,不管意图 |
| 环境 | 自动编译,本地跑通不算数 | 防不了"CI跑通了但生产环境不一样" | 只管CI环境,不管生产环境 |
| 质量 | 成品校验,没测过不让合 | 防不了"测试写了但没覆盖边界" | 只管测没测,不管测得全不全 |
| 科研 | 追根溯源,数据来源可验证 | 防不了"数据是真的但模型是错的" | 只管来源,不管结论 |
| 项目 | 契约对应,字段不对齐不让合 | 防不了"字段对齐了但逻辑是错的" | 只管接口,不管实现 |
| 容灾 | 异地容灾,主分支和缓存分支隔离 | 防不了"两个分支都错了" | 只管隔离,不管正确 |
| 行为 | 行为记录,谁干了什么全留痕 | 防不了"记录了但没人看" | 只管留痕,不管阅读 |
最后几句人话:
CICD不是万能的,但不加这玩意基本等于赌博。
CICD防得了搞事的,防不了偷懒的。
CICD能记录搞事证据,做不到后续追责。
CICD能防住家里养不熟的猫,但防不住黑客攻击。
我知道此时那些巨婴读者们想在评论区骂我,但我不在乎。我凭什么写?凭我自己真的碰见过多次事故。真话说出来必然会刺痛部分群体,但这篇不是毫无意义的引战,是思辨。
我拆的是一种思维类型,而不是一个个体,不存在所谓人身攻击。
真正的工程环境,是不会跟你讲情绪的。
工程,不是只有结果,但最看结果,最看你能不能按要求办事。
不能?那就不得不上强制措施了。
不是老板对你太严格,而是你没能做到让老板放心。
成年人,尤其是职场的成年人,要有责任意识。
你没证明自己值得别人合作,那你最好别上这个谈判桌。
......
除非你不后悔。
附:第十六期自测题
第一题:你的团队有没有CI?
- 有,且是强制门禁(不通过不能合并)
- 有,但不是强制门禁(可以手动绕过)
- 没有,靠人盯人
- 不知道什么是CI
如果你的答案是后两个,你就是在赌。
第二题:你的CI拦住了什么?
- 时间:封仓后不能提交
- 权限:不能动别人的模块
- 环境:本地跑通不等于CI跑通
- 测试:没测过不让合
- 数据:模型改了,数据必须跟着改
- 接口:字段不对齐不让合
- 容灾:主分支和缓存分支隔离
- 行为:谁在何时何地干了什么,全记录
拦不住的,就是你正在赌的。
第三题:你在CI里,是哪种人?
- A组:没有CI,没有规矩,出事就甩锅
- B组:没有CI,靠自觉,人走规矩散
- C组:有CI,被系统管,但开始学规矩了
- D组:有CI,自己守规矩,还能建规矩
A组被淘汰,B组在赌,C组在学,D组在跑。
第四题:你敢不敢回答这个问题?
你上次force push是什么时候?
- 我从来不用force push,因为知道后果
- 我用过,但我知道错了
- 我用过,但我觉得没什么
- force push是什么?
如果你选第三个,你就是评论区要骂我的那个人。
如果你选第四个,你就是A组。
第五题:最后一题
你后悔吗?
- 不后悔,我会继续
- 后悔了,但不知道怎么办
- 后悔了,我已经开始改了
- 我不知道你在问什么
后悔了不知道怎么办的,从第一题重新做。
后悔了已经开始改的,你正在从C组走到D组。
不后悔的,评论区见。
不知道我在问什么的,你就是A组。