先记住 5 个句子
所有操作都能从这五句话推导出来。
保存一次项目快照,并指向父提交。提交发生在本地。
不是复制一套仓库,而是给某条开发线的最新提交起名字。
通常指向当前分支;新 commit 会让当前分支指针向前移动。
origin 只是常用昵称。origin/main 是本地记录的远程跟踪指针,并非实时网页。
提议把 head 分支合入 base 分支,并承载讨论、审核、CI 与合并。
底层模型:代码在四个区域之间流动
命令本身并不神秘,它们只是读取、生成或移动这些区域中的状态。
你正在编辑的文件。此时变化还没有进入任何提交。
git diff下一次提交要包含的精确快照。它不是“上传区”。
git diff --staged本机完整历史、分支、标签及远程跟踪信息。
git log --graph --allfetch / pull
团队共享仓库。PR、Review 和 CI 是 GitHub 的协作层。
origin/main分支不是文件夹:它只是指向 commit 的名字
创建分支
git switch -c feature/login
新分支最初和当前分支指向同一提交。只有产生新 commit 后,两条指针才真正分开。
切换分支
git switch main
HEAD 改为指向 main,工作区随之还原成 main 所指提交对应的文件状态。
查看全图
git log --oneline --graph --decorate --all
这条命令最适合判断:我在哪里、各分支指向哪里、历史有没有分叉。
团队日常主流程
点击任一步骤查看命令、目的、检查点和常见风险。新人只需先掌握这条主线。
同步 main
git switch main git pull --ff-only origin main
Merge、Rebase、Squash 到底是什么关系
Merge
把另一条历史接入当前分支。发生分叉时通常生成一个有两个父提交的 merge commit。
git switch main git merge feature/login
适合:共享分支、需要保留真实拓扑、不能改写已发布历史。
Rebase
找到共同祖先,把当前分支独有提交复制并重放到新基线上,因此 commit ID 会改变。
git switch feature/login git fetch origin git rebase origin/main
适合:自己独立使用的功能分支,在合并前整理和更新基线。
Squash Merge
GitHub 把一个 PR 的净变化压成目标分支上的一个提交。PR 内部零碎 commit 不成为 main 的祖先。
GitHub: Squash and merge
适合:中小团队主干,希望“一项功能 = main 上一个清晰提交”。
git push --force-with-lease,并先确认远程没有别人新增的提交。冲突处理:冲突不是错误,而是 Git 无法代替人做业务判断
1. 先确定当前动作
git status
确认正在 merge 还是 rebase,以及冲突文件清单。
2. 人工形成最终内容
删除 <<<<<<<、=======、>>>>>>>,运行测试。
3. 标记并继续
git add 文件git merge --continue 或 git rebase --continue
不想继续 merge
git merge --abort
尽量回到 merge 开始前。开始合并前最好保持工作区干净,否则恢复可能更困难。
不想继续 rebase
git rebase --abort
放弃整次 rebase,回到开始前的分支状态。不要在不理解的情况下连续执行 reset。
误操作恢复:先判断修改位于哪一层
工作区修改不想要
git restore path/to/file
恢复为暂存区/当前提交中的版本。未保存修改会永久丢失,先看 git diff。
已经 add,但不想让它进入下次 commit
git restore --staged path/to/file
只撤出暂存区,工作区修改仍保留。
最近一次 commit 错了,还没 push
git reset --soft HEAD~1
撤销提交但保留暂存状态。也可用 git commit --amend 修改最近提交。reset 会移动分支指针,适合尚未共享的本地历史。
公共分支上的已推送提交需要撤销
git revert <commit-id>
创建一个反向提交,不删除公开历史。团队主干上优先 revert,不要 reset 后强推。
分支删了、reset 错了、commit 看不到了
git reflog git switch -c rescue/<name> <commit-id>
reflog 记录本地 HEAD 和引用的移动,是本地救援工具。先创建救援分支固定目标 commit,再继续处理。
场景选择器:我现在到底该用什么命令
git switch main git status git pull --ff-only origin main
若失败,说明本地 main 与远程发生分叉;先检查本地是否有不该存在的提交,不要直接强推。
团队治理:命令规范不统一,流程一定会失控
| 领域 | 推荐规则 | 目的 |
|---|---|---|
| main / release | 使用 GitHub Rulesets 或 Branch Protection;禁止直接 push 和 force push | 确保正式代码只能经过受控入口 |
| Pull Request | 至少 1 名审核者;必须通过测试、lint、构建等状态检查 | 把质量门槛自动化、制度化 |
| 合并方式 | 普通功能默认 Squash and merge;特殊长期分支才用 merge commit | 统一主干历史结构 |
| 分支 | feature/、fix/、refactor/、docs/;合并后删除 | 便于识别责任和生命周期 |
| 提交 | 小而完整;建议 Conventional Commits:feat/fix/docs/refactor/test/chore | 便于日志、发布说明和回退 |
| 密钥 | 永不提交密码、token、私钥、生产配置;发生泄漏先轮换密钥 | 删除后续文件并不能自动清除 Git 历史 |
| 文件规范 | 维护 .gitignore 与 .gitattributes;大型二进制评估 Git LFS | 避免仓库膨胀和跨平台换行冲突 |
| PR 大小 | 一个明确目的,避免夹带无关重构和全仓格式化 | 降低审核、冲突和回滚成本 |
建议的首次配置
git config --global user.name "Your Name" git config --global user.email "you@example.com" git config --global init.defaultBranch main git config --global fetch.prune true git config --global pull.ff only
pull.ff only 会让有分叉的 pull 直接失败,迫使成员明确选择 merge 或 rebase,而不是无意生成合并提交。
建议的 PR 模板字段
- 背景与目标
- 修改范围与明确不包含的内容
- 测试步骤和结果
- 数据库、接口、部署或兼容性影响
- 风险、回滚方式、关联 Issue
命令速查
git status任何操作前后的第一条命令。
git diff / git diff --staged分别检查未暂存与已暂存变化。
git fetch origin获取远程变化,不整合到当前分支。
git pull --ff-only只允许安全快进;分叉时停止。
git push -u origin branch首次推送并设置 upstream。
git branch -vv查看本地分支及其上游和领先/落后状态。
git log --oneline --graph --decorate --all查看完整提交拓扑。
git show <commit>查看某个提交的内容和元数据。
git stash push -m "WIP"临时收起未完成修改;回来用 stash pop。
git cherry-pick <commit>复制单个提交到当前分支;谨慎使用,可能形成重复历史。
git revert <commit>公共历史的安全撤销方式。
git reflog寻找本地曾经指向过的 commit。
团队成员必须能回答的 8 个问题
- commit、branch 和 HEAD 分别是什么?
- origin/main 为什么不一定等于 GitHub 网页当前的 main?
- 当前在 feature 分支执行
git pull origin main会发生什么? - fetch 与 pull 的差别是什么?
- merge 为什么不会改写已有 commit,而 rebase 会?
- 什么情况下允许
--force-with-lease,什么情况下绝不允许? - 公共分支撤销为什么优先 revert,而不是 reset?
- PR 的 base 和 compare/head 应该如何选择?
官方资料
本指南的行为定义以 Git 和 GitHub 官方文档为准。