为什么你要学它
你有没有过这种经历:改了半天模型代码跑通了,第二天想回到旧版本对比,却发现文件被覆盖、找不到差异;或者和同学一起做项目,两个人改了同一份文件,手动粘贴半天才能合并;更糟糕的是——你跑了 3 天训练脚本,训练日志和权重文件散落在 model_v1_final_final.pt、model_v2_真的不改了.pt 这种混乱命名里。
Git 就是为了解决这些"版本失控"而生的。你可以把它理解成一台智能时光机 + 协作账本**:
- 时光机:每次
commit一次就是拍一张快照,随时可以回到任意历史版本 - 协作账本:多个人在同一份代码上并行开发,Git 能自动合并差异,并在无法自动合并时告诉你哪里冲突了
- 备份保险:推到 GitHub 后,你的代码不怕硬盘坏掉也不怕本地误删
对于 AI 开发者来说,Git 不只是"工具"——它是你能站在巨人肩膀上的门槛。你会 clone 别人的模型仓库、提 PR 贡献代码、用 Git 管理自己的实验版本。没有 Git,你很难说自己是合格的开发者。
一句话概览(快速版)
- 三区模型:工作区(你正在编辑的文件)→ 暂存区(
git add后进入"待提交"区)→ 本地仓库(git commit后永久保存的版本) - 分支并行:每个人在自己的分支开发,
merge或rebase合回主线,互不干扰 - Fork + PR:先 fork 主仓库到自己账号,改完发起 Pull Request,等待 Code Review 后合并
核心拆解
🔑 三区流转(工作区 → 暂存区 → 本地仓库)
你编辑的文件在"工作区"。git add 把它们送到"暂存区",意思是"我准备提交这些变更"。git commit 则把暂存区的内容永久保存到"本地仓库",生成一个带 ID 的版本快照。最后 git push 推到远程仓库(如 GitHub)。这四步是 Git 最核心的节拍:
code1 lines工作区(Working Directory) ──git add──▶ 暂存区(Staging Area) ──git commit──▶ 本地仓库(Local Repo) ──git push──▶ 远程仓库(Remote)
为什么要多一个"暂存区"?因为它让你可以挑选要提交的内容:你改了 10 个文件,但只想先提交其中 3 个功能相关的,剩下 7 个调试日志暂时留下一次再提交。如果没有暂存区,每次 commit 就只能全量提交,版本历史会很混乱。
🔑 高频命令速查
bash8 linesgit init # 在当前目录初始化一个新仓库 git clone https://github.com/you/repo.git # 克隆远程仓库到本地 git status # 查看当前状态(哪些文件改了、在哪个分支) git add . # 暂存当前目录全部变更 git add file.py # 只暂存某个文件 git commit -m "feat: 新增模型训练脚本" # 提交(写清楚变更内容 git log --oneline --graph # 查看简洁的提交历史图 git diff # 查看工作区与暂存区的差异
这 8 个命令覆盖了日常 80% 的场景。记住:**commit message 要写清楚"做了什么",别只写 "update",三个月后你自己都看不懂。
🔑 分支与合并(branch / switch / merge / rebase)
分支是 Git 的灵魂。每一个分支就是一条独立的开发线路:
bash6 linesgit branch # 查看所有分支(当前分支前面有 * git branch feat/train-loop # 创建分支 git switch feat/train-loop # 切换到分支 git switch -c feat/train-loop # 创建并切换(一步到位) git merge feat/train-loop # 把 feat/train-loop 合并到当前分支 git rebase main # 把当前分支的提交"嫁接"到 main 之后(让历史线性化)
merge vs rebase:两者都能把分支合起来,但哲学不同。merge 会生成一个"合并提交",保留完整历史(像真实发生过的事情);rebase 把你的提交重新放到目标分支之后,历史是直线(看起来更干净)。经验法则:**你自己一个人开发的私有分支可以 rebase;多人共享的分支不要 rebase,会把别人的历史改了。
🔑 临时储藏(stash)与查看历史(log)
你写了一半代码,突然要切到别的分支改 Bug,这时候用 stash 把工作区临时藏起来:
bash4 linesgit stash # 把当前未提交的变更藏起来 git stash list # 查看藏了哪些 git stash pop # 把最新的取出来(pop 会删除 stash) git stash drop # 删除指定 stash
查看历史:
bash3 linesgit log --oneline -n 20 # 最近 20 条提交 git log --author="Alice" # 只看 Alice 的提交 git reflog # 救命用:查看所有 HEAD 位置记录,包括已删除的分支/提交
git reflog 是救命稻草。你不小心 `reset 错删了分支或 reset ——reflog 几乎总能把它找回来。
🔑 GitHub 协作:Fork + Pull Request 流程
你不能直接 push 到别人的仓库(你没有权限)。所以流程是:
- 在 GitHub 网页上点 Fork,把别人的仓库复制一份到你自己账号
git clone你 fork 后的仓库到本地- 在你的仓库里创建特性分支开发
git push origin feat/my-feature推到你自己 fork 的仓库- 在 GitHub 网页上点 New pull request,从你的分支往原仓库 main 提 PR
- 等 Code Review,有人给你评论你再改再 push,PR 会自动更新
- 被合并后可以删掉你自己的分支
完整命令:
bash15 lines# 1. 第一次克隆你 fork 的仓库 git clone https://github.com/you/awesome-ai.git cd awesome-ai # 2. 关联原仓库(方便同步最新代码) git remote add upstream https://github.com/original/awesome-ai.git # 3. 创建分支开发 git switch -c feat/add-demo # 4. 改完提交 git add . && git commit -m "feat: 添加 Streamlit demo" git push origin feat/add-demo # 5. 在 GitHub 网页提 PR # 6. 同步原仓库最新代码到本地 git fetch upstream git switch main git merge upstream/main
🔑 冲突解决
两个人改了同一份文件的同一行,Git 不知道该留谁的,就会发生"冲突"。冲突的文件会长这样:
code5 lines<<<<<<< HEAD 你当前分支的内容 ======= 对方分支的内容 >>>>>>> feature-x
解决冲突三步走:
- 打开冲突文件,手动编辑保留想要的内容(删掉
<<<<<<<、=======、>>>>>>>这些标记) git add解决后的文件git commit(merge 冲突)或git rebase --continue(rebase 冲突)
bash4 linesgit merge feature-x # 出现冲突 # 编辑冲突文件 git add resolved_file.py git commit # 完成合并提交
经验:冲突不可怕,可怕的是不敢面对。越早解决越轻松。
🔑 .gitignore(忽略不该被跟踪的文件)
AI 项目里有大量文件不该被 Git 跟踪:模型权重文件 .pt、.pth、虚拟环境 .venv/、Python 缓存 __pycache__/、日志 *.log、数据集 data/ 等。把它们写在 .gitignore 里,Git 会自动忽略:
code11 lines__pycache__/ *.pyc .venv/ *.pt *.pth *.safetensors *.onnx data/ logs/ *.log .DS_Store
模板可以去 gitignore.io 生成对应语言的标准模板。不要把大文件(尤其是超过 100MB 的)提交进 Git,否则仓库会变得极慢,甚至无法推送到 GitHub。
完整跑通方案
第一步:安装并配置 Git
bash11 lines# 安装: # Windows:去 https://git-scm.com 下载安装包,或用 winget install Git.Git # macOS:brew install git # Ubuntu:sudo apt install git # 配置全局用户信息(所有仓库通用) git config --global user.name "Your Name" git config --global user.email "you@example.com" # 查看配置 git config --list
第二步:从零创建一个本地仓库并提交第一个版本
bash27 linesmkdir my-ai-project cd my-ai-project git init # 创建 .gitignore cat > .gitignore << 'EOF' __pycache__/ *.pyc .venv/ *.pt *.pth data/ logs/ EOF # 创建 README 和训练脚本 echo "# My AI Project" > README.md echo "print('hello')" > train.py # 第一次提交 git add . git commit -m "chore: 初始提交,包含训练脚本和 .gitignore" # 在 GitHub 创建同名空仓库后,关联并推送 git remote add origin https://github.com/you/my-ai-project.git git branch -M main git push -u origin main
第三步:在特性分支上开发,然后合并回主线
bash16 lines# 从 main 创建并切换到新分支 git switch -c feat/add-loss-plot # 假设你修改了 train.py,添加了画图逻辑 git add train.py git commit -m "feat: 添加训练 loss 曲线绘制" # 回到 main 分支并合并 git switch main git merge feat/add-loss-plot # 推送 git push origin main # 删除已经合并过的分支(可选) git branch -d feat/add-loss-plot
第四步:在 GitHub 上 Fork 别人的项目并提 PR
bash18 lines# 1. 在 GitHub 网页上 Fork 原仓库(例:huggingface/transformers) # 2. 克隆你自己 fork 后的仓库 git clone https://github.com/you/transformers.git cd transformers # 3. 关联原仓库(方便以后拉取最新代码) git remote add upstream https://github.com/huggingface/transformers.git # 4. 创建特性分支 git switch -c fix/doc-typo # 5. 做修改并提交 echo "# 改动内容" git add . git commit -m "docs: 修复 README 中拼写错误" git push origin fix/doc-typo # 6. 回到 GitHub 网页,点 "Compare & pull request" 提 PR
第五步:解决一次 merge 冲突
bash8 lines# 场景:你在 main,准备合并 feature 分支,出现冲突 git merge feature # Git 提示哪些文件冲突了(both modified) # 打开冲突文件手动修改,保留需要的部分,删除 <<< === >>> 标记 git add <冲突文件> git commit # Git 会自动生成一个合并提交 # 结束
第六步:git stash 临时保存未完成工作
bash8 lines# 你正在开发到一半,突然要去 main 分支修 Bug git stash # 去修 Bug git switch main # ... 修完 Bug 并 commit # 回到开发分支 git switch my-feature git stash pop # 把之前藏的工作取出来继续
常见误区
误区 1:把大文件(模型权重、数据集)提交进 Git → 仓库膨胀,git push 失败、clone 慢得要死
解释:Git 是为文本代码设计的,它会永久保存每个版本的完整副本。一旦把 500MB 的 .pt 文件 commit 了,即使后来删除,文件仍然在历史记录里,仓库体积会暴涨,GitHub 也会拒绝超过 100MB 的文件推送。解决方法:用 .gitignore 忽略它们,用专门的大文件存储(LFS)或对象存储(S3/OSS)存模型权重和数据集。
误区 2:commit message 写 "update" 或 "fix" → 三个月后你自己也看不懂改了啥
解释:commit message 是写给未来的自己和你的协作开发者看的。好的格式:feat: 添加学习率调度器、fix: 修复 DataLoader worker 导致的死锁问题、docs: 更新 README 中的依赖安装说明。规范推荐:Conventional Commits(feat/fix/docs/chore/refactor/test)。
误区 3:直接在 main 分支上开发 → 每次都在 main 分支直接开发,出了问题没法回退、没法并行开发
解释:永远在特性分支上开发,完成后合并回 main。main 应该永远是"可运行、可发布"的稳定版本。规则简单:**一人一分支一功能。
误区 4:多人共享的分支上 rebase → 别人拉你的分支被你 rebase 后,其他人的历史混乱了
解释:rebase 会重写提交历史。如果别人已经基于你的分支 pull 过了,你再 rebase 会让别人 pull 时产生冲突或额外的合并提交。规则简单:只在自己一个人用的私有分支 rebase;共享分支用 merge。
误区 5:不写 `.gitignore` 就 `git add .` → 把 IDE 配置文件、系统隐藏文件、虚拟环境全 commit 进去了
解释:.gitignore 是项目一创建就要第一时间写好的文件。常见的应该忽略:__pycache__/、*.pyc、.venv/、*.pt、*.pth、*.log、data/、logs/、.DS_Store、.idea/、.vscode/ 等。
误区 6:`git push -f` 强制推送到共享分支 → 别人的提交被你覆盖掉了
解释:-f(--force)会强制覆盖远程分支,非常危险。除非你明确知道自己在做什么(比如你自己一个人的私有分支),否则永远不要在 main 或 develop 等共享分支上 force push。需要时先用 git push --force-with-lease 更安全(如果远程有你没见过的新提交就拒绝)。