60天企业 AI 实战训练营 · 阶段 1 · 第 1 周
Git 与企业
软件开发规范
建立版本管理、多人协作与可追溯交付意识
Day 04
讲师 · 包学斌
2026 · 09
含实操 · 请自带电脑
按 → 或 空格键 翻页 · F 全屏
今天这堂课解决什么问题
课程目标
01
版本管理
每一次修改都有快照、能对比、能回滚,不再依赖"最终版_真最终版"。
02
多人协作
分支 + Pull Request + Code Review,团队并行开发而不互相覆盖。
03
可追溯交付
谁在何时改了什么、为什么改,都能回答;任意历史版本可复现。
它在 60 天课程中的位置
Day 2-3 · Python 企业开发基础已完成
Day 4 · Git 与企业软件开发规范今天
Day 5 · Docker 与 AI 运行环境下一课
Day 6 · HTTP、REST API 与 FastAPI
阶段 1 交付底线:Git 管理 · Docker 部署 · 结构化日志 · 健康检查 —— Git 是第一道门槛
互动 · 举手投票 + 点击选择
你现在是怎么管理代码的?
凭直觉点一个,别想太久 —— 没有标准答案,只有真实习惯
点一个选项,看看它意味着什么 →
Part 01 · 为什么需要 Git
没有 Git 的世界:文件地狱
一个真实的分享目录
采购对账方案.pptx
采购对账方案_v2.pptx
采购对账方案_v2_修改.pptx
采购对账方案_v2_最终版.pptx
采购对账方案_v2_最终版_真最终版.pptx
三个月后:哪个是对的?哪个敢删?
有 Git 的世界:一条时间线
v1 · feat: 初版对账方案
v2 · feat: 加入供应商分组
v3 · fix: 修正金额口径
每一版都有名字、说明和作者 —— 想回到任何一版,一条命令。
Git 的答案:给每一次修改拍"快照",历史不可变,随时精确回退 —— 不靠文件名,靠提交记录。
Part 01 · 版本控制思想
版本控制的前世今生:四代进化
Git 不是凭空发明的 —— 它是 50 年"管住时间"的答案
史前 — 今天
① 手工备份
复制文件夹、改名存档,文件名就是版本号
→
1972 · RCS / CVS
② 本地版本控制
单机数据库记录每次改动,能回滚了
→
2000 · SVN
③ 集中式版本控制
一台中央服务器,大家 checkout / commit
→
2005 · Git
④ 分布式版本控制
每人一个完整仓库镜像,历史即数据
版本控制的本质:把"时间"变成可查询的数据 —— 快照可回溯、分支可并行、历史可审计。Git 把这条思想推到了极致。
Part 01 · Git 的设计哲学
起源决定设计:为 Linux 内核而生
2005 年 Linus 定下的硬指标,如今成了 Git 的灵魂:
比一切现有工具快
支持上千并行分支
完全分布式
历史不可篡改
快照,而非差异
每次 commit 记录整个项目的完整目录树状态,像给项目拍照,而不是存"改了哪几行"。
分布式
每个人本地都有完整历史,断网也能提交、回退、看历史;远程仓库只负责同步,不是中心。
历史不可变
用 SHA-1 哈希寻址,任何内容改动都会产生新的提交 —— 历史被"新建",不是被"改写"。
再深一层:Unix 哲学
每个命令只做一件事,自由组合成工作流;Git 底层是一个"内容寻址的文件系统",版本控制只是它上面的一个应用 —— 所以它几乎什么都能管:代码、文档、配置、模型。
Part 01 · 人物故事
Linus Torvalds:一次被逼出来的传奇
Linus Torvalds
1969 · 芬兰赫尔辛基 —— Linux 与 Git 之父
"我用自己的名字命名项目:先是 Linux,现在是 Git。"(git = 英式俚语"讨厌鬼")
1991
21 岁的大学生发布 Linux 内核 —— "Just a hobby, won't be big and professional."(只是个爱好,成不了大器)
2002
内核团队用专有软件 BitKeeper 管理代码 —— 全球最大的开源项目,核心工具却不开源,社区里埋着一根刺。
2005
BitKeeper 免费授权被收回。Linus 闭关两周写出 Git:更快、支持上千并行分支、完全分布式 —— 随后接管整个内核源码管理。
2008
GitHub 上线 —— Git + 托管平台,全球开源协作自此引爆。
今天
Git 成为全球开发的事实标准;Linux 则真的"运行着世界"——手机、服务器、超级计算机。
"Talk is cheap. Show me the code." —— Linus Torvalds
Part 01 · 开源生态
Git 编织的开源世界
开源世界的事实标准 —— 一切协作从一次 commit 开始
规模:全球默认的协作基础设施
GitHub 1 亿+ 开发者、数亿仓库;npm / PyPI / Docker Hub 全部围绕 Git 仓库运转。
AI 时代:你的工具链也来自这里
PyTorch、Transformers、vLLM 都以 Git 仓库形态协作;你未来的第一份工作,大概率从 git clone 团队仓库开始。
规则:开源 ≠ 免费拿
遵守 License(MIT / Apache-2.0);走 issue → fork → PR 的贡献流程;尊重社区礼仪。向开源项目提交 PR,是最好的简历。
你已经每天都在使用开源。学会 Git,就是拿到加入这张协作网络的门票。
Part 01 · 为什么需要 Git
企业视角:为什么离不开 Git
这个 bug 是谁、什么时候引入的?
git blame / git log -p —— 每一行代码都能追溯到具体提交
可追溯
线上出问题,如何 5 分钟回到上一个版本?
git revert / git tag —— 版本之间可以精确切换
可回滚
三个月前发给客户的那版,还能原样复现吗?
tag + commit hash —— 任意版本可完整重建
可复现
在企业里,代码不是"写完就结束":能追溯、能回滚、能审计,才叫可交付。本课程的验收底线 —— 代码、文档、配置、测试均入 Git。
02
Part 02
Git 核心原理
不懂原理的命令是咒语,懂了原理才是工具
Git
对象数据库
三区模型
不可变快照
Part 02 · Git 核心原理
.git 目录:一个对象数据库
.git/
├── HEAD # 当前在哪个分支
├── config # 仓库配置
├── objects/ # 对象数据库(核心!)
└── refs/ # 分支 / 标签指针
仓库的本质:.git 目录里的对象数据库,外加一堆"指针"。删除工作区文件不丢历史,删掉 .git 才真的丢。
blob
文件内容快照 —— 只存内容,不存文件名
tree
目录快照 —— 记录"哪个文件名指向哪个 blob"
commit
版本快照 —— 指向一个 tree + 父提交 + 作者 / 时间 / 说明
tag
里程碑别名 —— 给某个 commit 起名字(如 v1.0.0)
SHA-1 = 内容指纹,40 位:e83c5163316f89bfbde7d9ab23ca2e25604af290
内容相同 → 哈希相同 → 全库自动去重;哈希不同 → 内容一定不同,这就是"不可变"的数学保证。
Part 02 · Git 核心原理
三区模型:add 与 commit 之间发生了什么
每点一次,观察文件 train.py 的位置变化(核心动画,请盯紧)
git add
→
git commit
→
train.py
git add train.py
挑选改动放进"购物车":决定哪些修改进入下一次提交。
git commit -m "feat: ..."
购物车内容打包成一个不可变快照,永久入库。
继续修改 → 循环
工作区出现新改动,重复 add / commit。每个阶段都可用 git status 查看。
Part 02 · Git 核心原理
Commit:一条不可变的时间线
HEAD → main
a1b2c3dc1
d4e5f6ac2
9b8c7d6c3
c1 · a1b2c3d
feat: 项目初始化
parent:无(第一个提交)
c2 · d4e5f6a
feat: 新增 sum()
parent:a1b2c3d
c3 · 9b8c7d6
test: 补充 sum 用例
parent:d4e5f6a
每个 commit = 内容(tree) + 父提交(parent) + 作者 / 时间 / 说明
HEAD 是"你现在在哪"的指针,main 是主分支的名字 —— 它们都只是指向某个 commit 的指针。
为什么说"不可变"?
改动任何一个字符 → 生成全新 hash;所谓"修改历史"(amend / rebase)其实是造出新提交。铁律:已推送到远程的历史,不去修改。
Part 02 · Git 核心原理
日常命令速查
左列推动流程,右列回答"刚才发生了什么 / 怎么回头"
# 把流程向前推进
git status # 看状态(最常用!)
git add train.py # 单个文件进暂存区
git add -A # 全部改动进暂存区
git commit -m "feat: x" # 暂存区 → 快照入库
git log --oneline # 一行一条看历史
git log --graph --oneline --all # 带分支图的历史
# 查看差异 · 后悔与恢复
git diff # 工作区 vs 暂存区
git diff --staged # 暂存区 vs 最近提交
git restore app.py # 丢弃工作区修改(慎用)
git restore --staged f # 移出暂存区(不加 -A 时)
git show a1b2c3d # 看某次提交改了什么
git reflog # 后悔药:找回"消失"的提交
本地仓库
你的电脑 —— add / commit / branch 随便折腾,断网也能提交
远程仓库
企业内网 GitLab / GitHub / Gitee —— 团队协作与备份中心
新人心法:迷路时只做两件事 —— git status 和 git log --oneline,先看清现状再决定下一步。90% 的"Git 恐慌"都靠这两条命令化解。
实操 ① · 8 分钟 · 每人一台电脑
第一次提交
1新建并进入仓库:git init day04-lab && cd day04-lab
2新建 hello.py,打印你的名字
3git status —— 观察红色 untracked 状态
4git add hello.py → 再 git status,看颜色变化
5git commit -m "feat: 项目初始化"(用规范 message)
6git log --oneline 验证你的第一条历史
验收标准
git log --oneline 有一条 feat: 开头的提交
git status 显示 working tree clean
新人心法
迷路时只做两件事:git status 和 git log --oneline —— 先看清现状,再决定下一步。
卡住就举手 —— 实操环节助教会巡场
互动 · 快问快答
对错判断:三道送命题
先举手投票,再点击揭晓答案
1. commit 之后,我的代码就绝对安全了?
没 push 之前,历史只存在你自己电脑上 —— 硬盘一坏,照样全丢。
✗ 错
2. add 之后又改了文件,直接 commit 会包含最新修改?
暂存区记录的是 add 那一刻的内容;新修改需要再次 add。
✗ 错
3. rm 删了文件后,git add -A 再 commit,这次删除会进入历史?
对 —— 删除也是一次变更;Git 如实记录"哪个提交删了它"。
✓ 对
03
Part 03
Commit 规范
让三个月后的你,还看得懂历史
Git
反面教材
Conventional Commits
找茬游戏
Part 03 · Commit 规范
两种历史,两种命运
这样写,等于没写
update
修改
fix bug
改好了
asdfgh
排查问题时,你无法从历史里获得任何线索。
三个月后依然看得懂
fix: 修复金额合计 float 精度丢失
feat: 供应商对账单导出 Excel
docs: README 补充启动步骤
refactor: 抽出公共求和函数
类型 + 一句话说清"做了什么",历史即文档。
核心原则:一次 commit = 一个逻辑变更(代码 + 对应测试 + 相关文档一起提交)—— 这是为了 code review 方便,也是为了能精确回滚。
Part 03 · Commit 规范
Conventional Commits:团队通用格式
<type>(<scope>): <subject>
例:feat(ocr): 新增发票字段抽取
为什么企业强制要求?
工具可以按 type 自动生成 CHANGELOG、按版本检索历史、在 code review 里快速判断改动性质 —— message 不是写给自己看的,是写给团队和工具看的。
互动 · 找茬游戏
这些 commit message 合格吗?
先心里给个判断,再点击揭晓
update code
✗
零信息量,等同于没写
fix: 登录接口偶发 500,调整超时重试
✓
类型 + 现象 + 动作,教科书式
feat + fix + 文档修改(37 个文件)
✗
一个 commit 只应包含一个逻辑变更
feat(user): 支持供应商批量导入
✓
类型 + 范围 + 动作,清晰
改好了
✗
三周后没人知道改了什么
refactor: 抽出对账金额计算公共函数
✓
重构类型使用正确,不影响行为
04
Part 04
分支与协作
多人并行开发,而不互相践踏
Git
分支 = 指针
merge · rebase
冲突处理
Part 04 · 分支与协作
分支:一个会移动的指针
每点一次,看下图发生什么
创建分支 = 写入一个 41 字节的指针文件,瞬间完成,零成本
c1
c2
c3
c4
c5
c6
main
main
feature/ocr
feature/ocr
① 建分支
git switch -c feature/ocr —— 只是复制了一个指针,仍指向 c4。
② 分支上开发
新提交 c5 挂在 feature 上;main 纹丝不动,互不干扰。
③ 合并回 main
merge 产生合并提交 c6,main 指针前移到 c6。
④ 删分支
main 永远保持"可发布";合并后 feature 分支删除,不留坟场。
Part 04 · 分支与协作
merge vs rebase:两条整合路线
merge:保留分叉,生成合并提交
历史如实反映"分了又合"的协作过程;团队合并 PR 的默认方式。
rebase:把提交"搬家"到主干末尾
f1'、f2' 是全新提交(新 hash);历史变成一条直线,更干净。仅用于自己的本地分支。
铁律
已经推送到远程、别人可能已拉取的公共分支 —— 绝不 rebase。否则每个人的本地历史都会错乱,团队一起爆炸。
Part 04 · 分支与协作
冲突:Git 无法替你做业务决定
main 分支
app.py 第12行
discount = 0.8 # 大促 8 折
+
feature/discount 分支
app.py 第12行
discount = 0.75 # 长期协议 7.5 折
→
# app.py —— 合并时 Git 插入的冲突标记
def calc_price(price):<<<<<<< HEAD discount = 0.8 # main:大促活动 8 折======= discount = 0.75 # feature:长期协议价 7.5 折>>>>>>> feature/discount return price * discount
冲突不是 Git 的 bug
同一区域被两条分支修改,Git 不猜 —— 它把两个版本摆到你面前,业务取舍由人来做。这恰恰是它可靠的原因。
Part 04 · 分支与协作
解冲突四步法
STEP 1
定位
git status 列出 both modified 的文件。
STEP 2
读懂两边
逐块比较双方业务意图 —— 是合并两边的逻辑,还是取一方?
STEP 3
手工合并
改出正确代码,删除三行冲突标记,不是机械地"选一边"。
STEP 4
提交并验证
add + commit 完成"一次合并";重跑测试才算真正解决。
高危操作警示
git checkout --theirs app.py 表示"全盘拿对方的版本"—— 你自己的修改全部丢失;反过来 --ours 则丢掉对方的。
去年某项目解冲突时误用,两名同事各丢两天工作量。解冲突用编辑器,不用覆盖命令。
Part 04 · 分支与协作
分支避坑清单
1
所有人直接在 main 上开发
没有隔离,随时互相踩踏,main 永远处于"半成品"状态 —— 不可发布。
2
长命 feature 分支,偏离主干几周
分支与 main 严重发散,最后合并即地狱:冲突上百处,没人敢解。
3
分支用完不删,变成坟场
一个月后 50 个分支,没人知道哪些还活着、哪个敢删。
小步分支:一个分支只做一件事
快合快删:生命周期以天计,不以月计
PR 走 Review:不直接 push main
main 永远可发布
实操 ② · 10 分钟 · 两人一组
双人冲突演练
1A、B 都从 main 出发:git switch -c feat-a / git switch -c feat-b
2两人改 config.py 的同一行:A 写 MODE = "TRAIN",B 写 MODE = "EVAL",各自 add + commit
3A 先合并回 main(顺利);B 再合并 → 冲突出现
4B 手工解冲突:讨论后改成 MODES = {"TRAIN": ..., "EVAL": ...},add + commit
5git log --graph --oneline 观察合并提交;跑 python config.py 验证
验收标准
合并提交出现在 --graph 历史里
脚本可运行,双方逻辑都保留
没有残留冲突标记
05
Part 05
企业协作流程
从"我一个人写"到"一个团队有纪律地交付"
GitLab
feature 分支
Pull Request
tag · SemVer
Part 05 · 企业协作流程
Feature 分支工作流:一道流水线
→
→
→
④ Pull Request
描述改动 + 关联需求
→
→
→
两道质量闸门
Review 挡住"写错的代码",CI 挡住"测不过的代码"。任何改动直接进 main,在企业里都是事故。
被 Review ≠ 被否定
批注是团队的知识共享;企业新人代码被改得"满屏批注",是成长最快的方式。
Part 05 · 企业协作流程
Tag 与语义化版本:给里程碑起名字
tag:commit 的静态别名
commit 哈希难记,tag 用来标记对人有意义的节点:UAT 版本、正式发布、模型迭代。
git tag -a v1.0.0 -m "首个发布版本"
配合 CI 自动发布
推送 tag → CI 自动构建 Docker 镜像、生成发布产物 —— Day 05 就会用到。
MAJOR · 破坏性变更
接口或数据格式不再兼容(如删了配置字段)→ +1,后两位归零。
MINOR · 新特性
向后兼容的新功能(如新增导出)→ +1,PATCH 归零。
PATCH · 修复
不改接口的 bug 修复 → +1。
常见坑:只在本地打 tag 忘记 git push --tags;命名混乱(v1、V1.0、release-1)—— 统一 v{MAJOR}.{MINOR}.{PATCH}。
06
Part 06
AI 项目仓库规范
让任何同事一天之内跑通你的项目
Bash
六大目录
.gitignore · LFS
密钥安全
README
Part 06 · AI 项目仓库规范
AI 项目的标准目录结构
ai-project/
├── src/ # 源代码
├── tests/ # pytest 测试
├── docs/ # 文档(与代码同版本)
├── data/ # 数据目录(不入库)
├── models/ # 模型权重(LFS / 外链)
├── config/ # 配置(example 入库)
├── .gitignore # 忽略规则
└── README.md # 项目门面
src
源代码,全部入库
tests
测试入库 —— CI 的粮食
docs
文档入库,与代码同版本,关键文档配图
data
不入库;README 写清"数据如何获取"
models
权重走 LFS 或对象存储 + 版本记录
config
config.example.yaml 入库,真实值不入
原则:代码、文档、配置、测试均入 Git;"大的和密的"不入库,只留一份"如何获取"的说明。
Part 06 · AI 项目仓库规范
.gitignore:把"大与密"挡在门外
# Python
__pycache__/
*.pyc
.venv/
venv/
# 数据与模型
data/
models/*.pt
# 环境与密钥(重点!)
.env
# 其他
*.log
.ipynb_checkpoints/
.DS_Store
判断标准
仓库里只放文本与源码,不放大数据与二进制。每次 add 前问一句:这文件三个月后还有意义吗?
Git LFS:大文件的正规通道
模型权重、数据集用 git lfs track "*.safetensors",仓库里只存指针文件,真实文件进 LFS 存储。
经验阈值
超过 10MB 想一想;超过 100MB 不要放普通 Git —— 一旦提交,历史里永远都在。
Part 06 · AI 项目仓库规范 · 互动讨论
三大血泪坑
1
把 venv / data / .env 提交进库
仓库膨胀几个 GB,clone 半小时 —— 新人体验直接劝退。
2
git rm 删了大文件,仓库却没变小
历史提交里仍然存在;要 filter-repo 重写历史,代价极大 —— 所以别让它进来才是重点。
3
.env 里的 API Key 被提交,日志里又打印了完整环境变量
密钥泄漏 —— 企业里等同于生产事故,后面是漫长的轮换与审计。
课堂讨论 · 2 分钟
密钥已经 push 到远程仓库,现在删掉 .env 再 push 一次,泄漏就消除了吗?
答案:不能
删除只影响最新版本;历史里密钥仍在,checkout 旧提交就能拿到。唯一正确做法:立刻作废并轮换密钥。密钥一旦进过 Git,就当作已泄漏。
Part 06 · AI 项目仓库规范
README:仓库的门面
1项目说明 —— 一句话说清做什么、为什么做
2环境要求 —— Python 版本、依赖、需要的模型 / API
3快速开始 —— 复制即可运行的命令序列
4目录结构 —— 每个目录干什么
5测试方法 —— pytest 怎么跑、看什么指标
6常见问题 —— 新人最常卡的三个点
验收标准(硬性)
新同事 clone 后,一天之内跑通 demo —— 做不到就是 README 不合格。
AI 项目额外必写
模型 / API 依赖及版本、数据获取方式、评测怎么跑 —— 这是 AI 项目与普通项目 README 的最大区别。
常见坑
README 停留在 TODO;启动命令与代码脱节;不写测试运行方法。
实操 ③ · 15 分钟 · 综合演练
从零搭一个规范仓库
1git init ai-demo,建立六大目录 + .gitignore + README
2config.example.yaml 入库;本地 .env 被 ignore 规则挡住
3写 src/sum.py + tests/test_sum.py,规范 commit 分步提交
4git switch -c feature/readme 补全 README → 合并回 main
5git tag -a v0.1.0 -m "第一个可运行版本"
验收清单
git log --oneline 全部是规范 message
git status 干净,.env 未被跟踪
git log --graph 合并历史清晰
git tag -n 看到带说明的 v0.1.0
新人视角:README 能照着跑通
总结
今天你带走了什么
起源
2005 年 Linus 为 Linux 写下 Git;如今 1 亿+ 开发者用它协作
原理
对象数据库 · blob / tree / commit / tag · SHA-1 寻址
规范
Conventional Commits:类型 + 一句话
版本
tag + SemVer:v{MAJOR}.{MINOR}.{PATCH}
仓库
六大目录 + .gitignore + LFS
视野
Git 编织开源生态 —— 你已是这张网络的候补成员
"Git 不是命令背诵,而是让每一次交付可追溯、可回滚、可协作。"
课后作业 · 明日预告
今天到此,工程起步
作业 1 · 迁移
把 Day 2-3 的 Pandas 脚本迁入规范仓库:六大目录 + .gitignore + 规范 commit 历史。
作业 2 · 文档与版本
README 写到"新人可跑通"标准,打 tag v0.1.0(带说明)。
作业 3 · 阅读
Pro Git 中文版第 1、2、3 章:git-scm.com/book/zh/v2;顺便读读 Git 诞生那两周的故事。
明日预告 · Day 05
Docker 与 AI 运行环境
今天我们把代码放进规范仓库;明天把整个环境打包成可复制的镜像 —— 让"在我电脑上是好的"这句话永远消失。
谢谢 · Q&A —— 实操问题随时在群里 @ 包学斌