目标读者:会写代码/做文档、需要版本管理与协作的你。
阅读收益:理解 Git 的核心模型;掌握从入门到高阶的常用命令与实际场景;遇到“翻车”能自救。
目录
- Git 是什么:底层模型一眼懂
- 安装与初始化配置(必须做)
- 你的第一个仓库:最小工作循环
- 查看与比较:log、diff、show 高效浏览历史
- 分支与合并:从 switch/merge 到 rebase
- 远程协作:origin、上游跟踪、push/pull/tag
- 忽略与清理:.gitignore、clean、rm –cached
- 回退与修复:restore、reset、revert、reflog
- 暂存与临时分支:stash 的正确姿势
- 历史重写与变基:amend、i-rebase、cherry-pick
- 查错利器:bisect 二分定位 bug
- 更专业的场景:worktree、sparse-checkout、LFS、submodule
- 钩子与自动化:pre-commit、commit-msg
- 安全与协作规范:签名、保护分支、冲突策略
- 性能与大仓库保养:gc、maintenance
- 常见工作流模板:Feature Branch、Git Flow、Trunk-Based
- 常见翻车与自救清单
- 命令速查(Cheat Sheet)
- 练习建议与进一步阅读
Git 是什么:底层模型一眼懂
一句话:Git 是一个内容寻址的快照数据库。每次提交(commit)记录了整个工作区的快照,并通过 SHA-1/对象 ID 唯一标识;分支只是指向提交的可移动指针。
- 四个区域:
工作区(Working Directory) → 暂存区(Index/Stage) → 本地仓库(Local Repository/.git) → 远程仓库(Remote) - 三种对象:blob(文件内容)、tree(目录)、commit(提交元数据 + 指向父提交 + 指向一个 tree)。
- HEAD:当前检出的提交/分支的指针。
HEAD -> main
表示“当前在 main 分支”;“分离头”则是HEAD
直接指向某个提交。
理解这个模型,剩下的是把各命令映射到这套心智模型。
安装与初始化配置(必须做)
# 配置身份
git config --global user.name "你的姓名或ID"
git config --global user.email "you@example.com"
# 设定默认分支名为 main(新 Git 默认已是 main,确保一致)
git config --global init.defaultBranch main
# 选择编辑器与差异工具(示例以 VS Code 为例)
git config --global core.editor "code --wait"
git config --global diff.tool vscode
git config --global difftool.vscode.cmd "code --wait --diff $LOCAL $REMOTE"
# 处理换行符(跨平台团队建议配合 .gitattributes,见下文)
git config --global core.autocrlf input # macOS/Linux 推荐
# git config --global core.autocrlf true # Windows 常见设置
# 体验增强(建议)
git config --global alias.st "status -sb"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global pull.rebase false # 团队统一策略很重要
提示:把
~/.gitconfig
提交到你自己的 dotfiles 仓库,换机也不怕。
你的第一个仓库:最小工作循环
1)初始化或克隆
git init # 在当前目录新建仓库
git clone <url> # 从远程克隆已有仓库
2)查看状态
git status # 最安全的命令,没有之一
git status -sb # 简洁视图(配合上面的 alias.st)
3)添加与提交
git add <file> # 把工作区变更加入暂存区(Stage)
git add -A # 一次性添加所有变更(新增/修改/删除)
git commit -m "feat: 初始化项目" # 新建提交
git commit --amend # 修改上一条提交(commit ID 会变)
4)忽略无关文件(先写好 .gitignore)
# 语言/框架生成的临时文件
node_modules/
dist/
*.log
.env
*.tmp
5)回看历史
git log --oneline --graph --decorate --all # 全局图
git show HEAD # 查看最近一次提交详情
最小循环口诀:
status → add → commit → log/show
。先忽略无关,少提交大二进制。
查看与比较:log、diff、show 高效浏览历史
git log --stat # 每次提交修改的文件与行数
git log -p # 带补丁(patch)的提交历史
git log --author="alice" --since="2025-01-01"
git diff # 工作区 vs 暂存区
git diff --staged # 暂存区 vs HEAD(将要提交什么)
git diff main..feature/login # 两个分支的差异(不含共同祖先以外)
git diff main...feature/login # 基于共同祖先的变更差异
git show <commit> # 看某个提交;文件视图:git show <commit>:path/to/file
小技巧:
-w
忽略空白变更:git diff -w
、git log -p -w
- 按文件过滤:
git log -- <path>
、git blame -L <start>,<end> <file>
分支与合并:从 switch/merge 到 rebase
创建与切换
git branch # 列出本地分支
git switch -c feature/login # 新建并切换
git switch main # 切回主分支(Git 2.23+ 推荐 switch/restore)
# 老命令:git checkout -b feature/login / git checkout main
合并(merge)
# 常规(可能 fast-forward,也可能产生 merge commit)
git switch main
git merge feature/login
# 禁止 FF,强制生成 merge commit 以保留分支语义
git merge --no-ff feature/login
合并冲突处理流程:
- Git 标记冲突文件,带
<<<<<<<
=======
>>>>>>>
- 手动或借助 IDE 解决 →
git add
标记已解决 git commit
完成合并(某些工具会自动生成 message)
变基(rebase)
# 将 feature/login 在 main 之上重放,得到更线性的历史
git switch feature/login
git rebase main
# 若冲突:解决 → git rebase --continue;放弃:git rebase --abort
何时用 rebase?
- 本地/私有分支:整理历史、压缩 commit,便于 review。
- 公共分支:不要随意 rebase(会重写历史,影响同伴)。
通用原则:公共历史用merge
,个人历史用rebase
。
远程协作:origin、上游跟踪、push/pull/tag
git remote -v # 查看远程
git remote add origin <url> # 绑定远程
git push -u origin main # 首次推送并建立跟踪关系
git branch -vv # 查看每个分支跟踪的上游
git fetch # 获取远程更新(不变更本地工作区)
git pull # fetch + 合并(或 rebase,取决于配置)
git pull --rebase # 显式以 rebase 同步
git push # 推送当前分支
git push --set-upstream origin feature/login
git push --force-with-lease # 安全强推(推荐,避免覆盖他人提交)
git push origin :old-branch # 删除远程分支
Tag(打标签/发版):
git tag -a v1.0.0 -m "First release"
git push origin v1.0.0
git tag -d v0.9.0
git push origin :refs/tags/v0.9.0
清理远程已删除的跟踪分支:
git fetch --prune
git remote prune origin
忽略与清理:.gitignore、clean、rm –cached
.gitignore
只对未被跟踪的文件生效。若已经被跟踪,要从索引移除再忽略:
git rm -r --cached .
git add .
git commit -m "chore: apply .gitignore"
- 清理工作区的未跟踪文件(先 dry-run 看看):
git clean -nfd # 预演
git clean -fd # 强制删除未跟踪的文件与目录
回退与修复:restore、reset、revert、reflog
三个层面的回退:
- 工作区文件:
git restore
- 暂存区:
git restore --staged
- 提交历史:
git reset
/git revert
/git reflog
# 丢弃工作区对某文件的修改
git restore path/to/file
# 取消暂存(从暂存区回到工作区)
git restore --staged path/to/file
# 回到旧提交(移动分支指针)
git reset --soft <commit> # 仅移动 HEAD,保留暂存区+工作区
git reset --mixed <commit> # 默认,清空暂存区,保留工作区
git reset --hard <commit> # 一切回到指定提交(危险)
# 生成一个“反向提交”,用于回滚已公开历史(安全)
git revert <commit>
# 救命指令:哪怕分支/提交丢了,reflog 常能找回
git reflog
git reset --hard HEAD@{3} # 将当前分支重置到 3 次操作之前的位置
口诀:
- 改工作区:
restore
;- 撤暂存:
restore --staged
;- 重写本地历史:
reset
;- 回滚公共历史:
revert
;- 一切都没了?用
reflog
找回。
暂存与临时分支:stash 的正确姿势
git stash push -m "WIP: 登录页样式" # 保存当前未提交的工作(含暂存内容)
git stash list
git stash show -p stash@{0} # 看差异
git stash apply stash@{0} # 应用但不删除
git stash pop # 应用并删除最近一次 stash
git stash branch tmp-fix stash@{0} # 从某个 stash 直接开分支继续
提示:不要把 stash 当“万能回收站”,定期清理;重要工作尽量 commit(哪怕是 WIP)。
历史重写与变基:amend、i-rebase、cherry-pick
git commit --amend # 修改最近一次提交(补充文件/改 message)
git rebase -i HEAD~5 # 交互式整理最近 5 次提交(squash/fixup/reword)
# 打开编辑器后:
# pick 1234 feat: A
# fixup abcd fix minor
# reword efgh change message
# 说明:pick=保留;squash=合并并编辑 message;fixup=合并但不改 message;reword=改 message
# 挑拣提交到当前分支
git cherry-pick <commit|range>
# 自动按 fixup!/squash! 前缀对齐:
git rebase -i --autosquash main
范围语法速读:
A..B
:A 不含、B 含(B 有而 A 没有的提交)A...B
:基于共同祖先的对比HEAD~3
:HEAD 的第 3 个父辈提交@{-1}
:上一次检出的分支/提交
查错利器:bisect 二分定位 bug
git bisect start
git bisect bad # 标记当前为坏版本
git bisect good <commit> # 标记某个已知好版本
# Git 自动二分跳转,重复标记 good/bad,直到找到最初坏提交
git bisect reset
在配套脚本或 CI 中,你可以让
bisect run
自动执行测试命令,显著加速定位回归。
更专业的场景:worktree、sparse-checkout、LFS、submodule
worktree:同一仓库多工作副本
git worktree add ../build-fix fix/build
git worktree list
git worktree remove ../build-fix
在不切换主工作区的情况下并行处理热修复与特性。
sparse-checkout:只检出需要的子目录(大仓库福音)
git clone --filter=blob:none --sparse <url>
cd repo
git sparse-checkout set packages/pkg-a packages/pkg-b
Git LFS:大文件友好
适合二进制/媒体资源:
git lfs install
git lfs track "*.psd"
git add .gitattributes
子模块(submodule)与 subtree
- submodule:指向外部仓库的特定提交,版本可控但操作相对繁琐。
- subtree:把外部仓库内容“嵌入”当前仓库,更新与合并较直观(需要额外命令支持)。
建议:如可选,用包管理/镜像服务优先,其次 subtree,再次 submodule。
钩子与自动化:pre-commit、commit-msg
- 本地钩子位于
.git/hooks/
,例如pre-commit
、commit-msg
。 - 配合工具(如 pre-commit 框架、lint-staged、Husky),可在提交前自动执行格式化、lint、检测敏感信息等。
示例:保证提交信息符合规范(如 Conventional Commits)
# .git/hooks/commit-msg (简化示例,真实项目用成熟工具)
#!/bin/sh
msgfile=$1
grep -E '^(feat|fix|docs|chore|refactor|test|perf|build|ci)(\(.+\))?: .{1,}' "$msgfile" || {
echo "❌ 提交信息不符合规范"
exit 1
}
安全与协作规范:签名、保护分支、冲突策略
签名提交(GPG/SSH)
git config --global commit.gpgsign true
git config --global user.signingkey <你的key ID>
# 或使用 SSH 签名(现代托管平台已支持)
保护主分支 & 评审流程
- main/prod 分支设保护:禁止强推、需 PR 审核、需通过 CI。
- 约定冲突解决策略:
- 合并参数:
-X ours
/-X theirs
(路径层面自动偏向) - 复杂冲突必须人工审查;记录决策。
- 合并参数:
性能与大仓库保养:gc、maintenance
git gc --aggressive --prune=now # 手动清理压缩(谨慎)
git maintenance start # 后台维护任务(现代 Git)
git count-objects -vH # 看看对象与尺寸
- 大仓库、历史上误入的大文件:用 git filter-repo(替代过时的 filter-branch)清理历史。
- 定期
fetch --prune
,避免远程垃圾引用拖慢操作。
常见工作流模板:Feature Branch、Git Flow、Trunk-Based
1)Feature Branch(最常见)
- 从
main
切出feature/*
- 提交 → PR → Review → Merge
- 发布用 Tag,必要时从
main
切hotfix/*
2)Git Flow(版本节奏强,适合传统发布)
main
(稳定) +develop
(日常)feature/*
基于 develop,release/*
合并回 main 与 develop,hotfix/*
基于 main
3)Trunk-Based(激进、快节奏)
- 所有变更尽快合入 trunk(main),通过 feature flags 控制开关,强依赖自动化测试。
选择建议:小团队/互联网偏 Feature Branch 或 Trunk-Based;有严格发布节奏与多版本维护的团队用 Git Flow。
常见翻车与自救清单
- 误删分支:
git reflog
找到删除前的提交 →git branch <name> <commit>
- 强推覆盖他人提交:
git reflog
查远程跟踪分支的之前位置(或同事的 commit)→ 新分支回收 → PR 修复 - 提交了敏感信息(Token/密码):
- 立刻废弃凭据;
- 用 git filter-repo 从历史清理;
- 强推并通知所有协作者
re-pull
(可能需--force-with-lease
)。
- 分离头上写了好一堆代码:
git branch save-work
给当前提交起个名,避免丢失。 - 冲突太多:
先git merge --abort
或git rebase --abort
;分步合并,按目录/文件拆解;开启git rerere
复用冲突解决。git config --global rerere.enabled true
命令速查(Cheat Sheet)
查看
git status -sb
git lg # 自定义别名:--oneline --graph --decorate --all
git show <commit|tag|HEAD>
git diff / git diff --staged
分支
git branch -vv
git switch -c <branch> # 新建并切换
git switch <branch>
git merge <branch>
git rebase <onto>
远程
git remote -v
git fetch --prune
git push -u origin <branch>
git push --force-with-lease
git pull --rebase
回退/修复
git restore <file> # 丢弃工作区
git restore --staged <file> # 取消暂存
git reset --soft/mixed/hard <commit>
git revert <commit>
git reflog
整理历史
git commit --amend
git rebase -i HEAD~N
git cherry-pick <commit|A..B>
其他常用
git stash {push|list|show|apply|pop|branch}
git tag -a vX.Y.Z -m "msg" && git push origin vX.Y.Z
git clean -nfd # 预演清理
git blame -L <m,n> <file>
git bisect start/bad/good/reset
git worktree add <path> <branch>
git sparse-checkout set <dir1> <dir2>
练习建议与进一步阅读
30 分钟上手练习脚本(可复制到任意空目录执行):
# 初始化与基本提交
git init demo-git && cd demo-git
echo 'hello' > app.txt
git add app.txt
git commit -m "feat: init app"
# 开分支与合并
git switch -c feature/greet
echo 'greet=你好' >> app.txt
git commit -am "feat: add greet"
git switch main
git merge --no-ff feature/greet -m "merge(feature/greet): add greet"
# 变基与整理
git switch -c feature/cleanup
echo 'tmp' > tmp.txt && git add tmp.txt && git commit -m "chore: tmp"
echo 'refactor' >> app.txt && git commit -am "refactor: app"
git rebase -i HEAD~2 # 将 chore: tmp 标记为 fixup 合并到 refactor
# 回退与自救
git reset --soft HEAD~1
git commit -m "refactor: app (clean)"
git reflog | head -5
进一步阅读(关键字方便你自行检索):
- Pro Git(免费电子书)
- “git flight rules”(故障排除的规则集)
- “Conventional Commits”“Keep a Changelog”
- “git filter-repo” 历史清理工具
- “Trunk-Based Development” 工作流
实战小建议(Best Practices)
- 小步提交:一次提交完成一个最小可描述的变更;消息清晰有前缀(feat/fix/docs…)。
- PR 尺寸可控:最好 < 300 行变更;大改动拆批;先提设计再写代码。
- 统一策略:团队就 pull 策略(merge/rebase)、分支命名、保护规则达成一致。
- 避免把密钥/大文件直接进仓库;必要时用 LFS 或外部存储。
- 多用“预演”:
git clean -nfd
、git reset --hard <hash>
前先git log
/git show
看清楚。 - 公共分支少 rebase,若必须重写历史,务必同步告知并使用
--force-with-lease
。
结语
掌握 Git 的关键不是死记命令,而是理解快照 + 指针的模型,再把常见场景映射到少数核心命令上。本文给出的套路和命令足以覆盖 90% 的日常与进阶需求。遇到极端翻车别慌,reflog
往往能救命。