Git 工作流完全指南:从工作流选型到高频命令
大家好,我是云萱。
Git 是每个开发者的日常工具,但很多人对 Git 的理解停留在 add/commit/push/pull 这个层面。一到面试被问到”你们团队用什么工作流”、“merge 和 rebase 的区别”、“怎么处理大仓库”就卡壳。
这篇文章把我整理的 Git 知识系统地梳理一遍——从工作流选型到高频命令,从冲突解决到大仓库优化,尽量覆盖全面。
一、四种常见 Git 工作流
没有”最好的”工作流,只有最适合你们团队的。关键是要理解每种工作流的适用场景和 trade-off。
1. Git Flow(最经典)
master (生产) ──────────────────●───────────────●───
\ /
release (预发布) ────────────●───●─────────────●───
\ /
develop (开发) ──●──●──●──●───●──●──●──●──●──────────
\/ \/ /\ /\
feature/xxx ●──● ●──● ● ●
特点:
- 分支多,流程规范,适合版本发布节奏明确的项目
- 有
master(生产)、develop(开发)、release(预发布)、feature(功能)、hotfix(热修)五种分支 - 适合有明确版本周期的传统软件
适用场景: 传统企业软件、有明确版本号的产品、发布频率不高的团队。
2. GitHub Flow(最简洁)
main ────────●───────●───────●───────
\ / \ / \
feature/xxx ●──● ●──● ●──●
PR PR PR (review + CI)
特点:
- 只有一个长期分支
main,功能分支短期存在 - 配合 Pull Request + CI/CD,适合持续部署
- 互联网公司最常用
适用场景: SaaS 产品、持续部署、发布频率高的团队。
我目前的项目主要用这种模式。
main分支随时可发布,每个功能开 feature 分支,提 PR,CI 跑通 + review 通过就合入,合进去自动部署。简单高效。
3. GitLab Flow(带环境分支)
production ────────────────●─────────●──
↑ ↑
staging ──────────●───────●────●────●──
↑ ↑ ↑
main ──●──●────●───●──●────●────●────●──
\/ \/ \/
feature ●──● ●─● ●──●
特点:
- 在 GitHub Flow 基础上增加环境分支(staging / production)
- 代码向上游合并,部署向下游推进
- 适合有多个部署环境的团队
适用场景: 有明确的测试/预发布/生产环境分层的团队。
4. Trunk-Based Development(TBD)
main ──●──●──●──●──●──●──●──●──●──
(short-lived feature flags)
特点:
- 所有人直接往 main 提交(或极短生命周期的 feature 分支,几小时到一天)
- 用 feature flag 控制未完成功能的开关
- 配合强 CI,适合高频率发布的团队
- Google、Meta 这种级别的公司普遍采用
适用场景: 超大规模团队、极高发布频率、工程能力强的团队。
二、高频操作速查
1. 提交与回滚
这是面试最高频的考点,必须说清楚。
| 场景 | 命令 | 说明 |
|---|---|---|
| 修改最后一次提交 | git commit --amend | 还没 push 的时候用 |
| 撤销最后一次提交(保留修改) | git reset --soft HEAD~1 | 提交的文件回到 staging |
| 撤销最后一次提交(丢修改) | git reset --hard HEAD~1 | ⚠️ 彻底丢掉,谨慎用 |
| 回滚某次提交(生成新提交) | git revert <commit-hash> | 安全,适合已 push 的提交 |
| 撤销工作区修改 | git checkout -- <file> 或 git restore <file> | 还没 add 的时候 |
| 撤销 add | git reset HEAD <file> 或 git restore --staged <file> | add 了但还没 commit |
reset 三种模式的区别(面试必问):
--soft : 只动 HEAD 指针,staging 和工作区都不动
--mixed : 动 HEAD + staging(默认模式),工作区不动
--hard : HEAD + staging + 工作区全动,彻底丢修改 ⚠️
简单记:soft 最温柔(只动指针),hard 最暴力(全丢),mixed 在中间。
2. 分支操作
# 查看所有分支
git branch -a
# 创建并切换
git checkout -b feature/xxx # 老方式
git switch -c feature/xxx # 新方式(更语义化,推荐)
# 删除本地分支
git branch -d feature/xxx # 已合并的分支
git branch -D feature/xxx # 强制删除(未合并也删)
# 删除远程分支
git push origin --delete feature/xxx
# 清理远程已删除的分支引用
git remote prune origin
git fetch --prune
3. merge vs rebase(面试高频)
merge(合并):保留完整历史,生成一个 merge commit
git checkout main
git merge feature/xxx
rebase(变基):历史更线性,看起来像直接在上面堆的
git checkout feature/xxx
git rebase main
什么时候用哪个?黄金法则:
- 公共分支(main/develop)的合入用 merge —— 保留完整历史,记录合并关系
- 自己的 feature 分支同步 main 的更新用 rebase —— 历史线性干净
- ❌ 不要在公共分支上 rebase! 会改写别人的历史,导致所有人冲突
4. 冲突解决
# 查看冲突文件
git status
# 标记冲突已解决
git add <file>
# merge 冲突解决完后
git commit
# rebase 冲突解决完后
git rebase --continue
# 不想搞了,中止 rebase
git rebase --abort
解决冲突的小技巧:
- 先理解两边改了什么,不要只看”哪边留下”
- 复杂冲突建议找原作者一起过
- 冲突解决完编译跑一遍测试,确认没改坏
5. 暂存(stash)
# 暂存当前修改
git stash
git stash save "描述信息" # 带描述,方便找
# 查看暂存列表
git stash list
# 恢复最新暂存(并删除)
git stash pop
# 恢复但不删除
git stash apply
# 删除某个暂存
git stash drop stash@{0}
# 清空所有暂存
git stash clear
三、排查问题常用命令
# 查看提交历史
git log --oneline --graph --all # 图形化历史,最常用
git log -p <file> # 查看文件的修改历史
git log --author="name" # 按作者过滤
git log --since="2024-01-01" # 按时间过滤
# 查看某次提交改了什么
git show <commit-hash>
git show <commit-hash> --stat # 只看改了哪些文件
# 比较差异
git diff # 工作区 vs staging
git diff --staged # staging vs HEAD
git diff main feature/xxx # 两个分支比较
# 谁写的哪行代码(甩锅神器 😏)
git blame <file>
git blame -L 10,20 <file> # 只看 10-20 行
# 二分查找引入 bug 的提交
git bisect start
git bisect bad # 当前版本有 bug
git bisect good v1.0 # v1.0 是好的
# 然后逐个测试,标记 good/bad,git 会自动找到第一个坏提交
git bisect reset # 结束后回到原位
git bisect 真的是神器——当你不知道哪个 commit 引入了 bug,用二分法快速定位,效率很高。
四、大仓库优化
面试常问:Git 仓库很大很慢怎么办?
-
浅层克隆:只拉最近 N 个提交
git clone --depth=1 <repo-url> # 只拉最新 git clone --depth=50 <repo-url> # 拉最近 50 个 -
只拉单个分支
git clone --single-branch -b main <repo-url> -
稀疏检出(sparse checkout):只 checkout 部分目录
git sparse-checkout init git sparse-checkout set app/ config/ -
Git LFS:大文件(图片、二进制、模型文件)用 LFS 存,不占 git 历史体积
-
历史大文件清理:
git filter-repo或 BFG Repo-Cleaner
五、Commit Message 规范
推荐 Conventional Commits 格式:
<type>(<scope>): <subject>
<body>
<footer>
Type 类型:
feat: 新功能fix: 修复 bugdocs: 文档style: 格式(不影响代码运行)refactor: 重构(不是新增也不是修 bug)perf: 性能优化test: 测试chore: 构建/工具/依赖等杂事
示例:
feat(user): 添加用户登录功能
- 支持邮箱密码登录
- 支持 OAuth2 第三方登录
- 增加登录限流防止暴力破解
Closes #123
规范的 commit message 有什么用?
- 自动生成 CHANGELOG
- 自动决定版本号(semantic-release)
- 代码历史可读性高
- 回滚的时候一看就知道这个 commit 是干嘛的
六、面试中常被问到的
Q: 你们团队用什么 Git 工作流?为什么?
结合实际说,重点讲清楚为什么选这个,而不是只会说名字。 比如:“我们用 GitHub Flow,因为我们是 SaaS 产品,持续部署, main 分支随时可以发布。PR + CI + review 的模式足够了, 不需要 Git Flow 那么多分支增加复杂度。”
Q: merge 和 rebase 的区别?什么时候用哪个?
merge 保留完整历史,生成 merge commit;rebase 让历史线性干净。 公共分支合入用 merge,自己的 feature 分支同步用 rebase。 黄金法则:不要在公共分支上 rebase。
Q: Git 的对象类型有哪些?
blob(文件内容)、tree(目录结构)、commit(提交)、tag(标签) 都是用 SHA-1 哈希标识的。
Q: 怎么理解 Git 是分布式的?
每个 clone 都是完整的仓库,有完整的历史,可以本地提交、查看历史, 不需要联网。不像 SVN 那种集中式,服务器挂了就干不了活。
Q: 怎么把一个 repo 的某个目录拆成独立 repo 并保留历史?
git filter-repo --path <dir> --subdirectory-filter <dir>或者用git subtree split
写在最后
Git 是个日常工具,但用得好和用得一般差距挺大的。会 commit/push/pull 只能算入门,理解工作流的选型、知道各种场景下的最佳实践、能处理复杂问题,才是进阶。
最关键的一点:Git 的操作大部分都是可恢复的(只要 commit 过),不用太怕。实在搞不定了,git reflog 可以救你。
希望这篇文章对你有帮助~