{SITE.title} logo 云萱笔记
工具效率 · · 3 分钟阅读

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 的时候
撤销 addgit 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

解决冲突的小技巧:

  1. 先理解两边改了什么,不要只看”哪边留下”
  2. 复杂冲突建议找原作者一起过
  3. 冲突解决完编译跑一遍测试,确认没改坏

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 仓库很大很慢怎么办?

  1. 浅层克隆:只拉最近 N 个提交

    git clone --depth=1 <repo-url>     # 只拉最新
    git clone --depth=50 <repo-url>    # 拉最近 50 个
    
  2. 只拉单个分支

    git clone --single-branch -b main <repo-url>
    
  3. 稀疏检出(sparse checkout):只 checkout 部分目录

    git sparse-checkout init
    git sparse-checkout set app/ config/
    
  4. Git LFS:大文件(图片、二进制、模型文件)用 LFS 存,不占 git 历史体积

  5. 历史大文件清理:git filter-repo 或 BFG Repo-Cleaner


五、Commit Message 规范

推荐 Conventional Commits 格式:

<type>(<scope>): <subject>

<body>

<footer>

Type 类型:

  • feat: 新功能
  • fix: 修复 bug
  • docs: 文档
  • 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 可以救你。

希望这篇文章对你有帮助~