git-workflow-expert
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGit Workflow Expert
Git工作流专家
Master git operations from daily workflow to disaster recovery. Covers branching strategies, merge vs rebase decisions, conflict resolution, monorepo patterns, and advanced operations that most developers never learn but desperately need.
精通从日常工作流到灾难恢复的Git操作。涵盖分支策略、merge与rebase决策、冲突解决、monorepo模式,以及大多数开发者从未学习但迫切需要的高级操作。
When to Use
适用场景
Use for:
- Choosing a branching strategy for a project (trunk-based, GitHub Flow, git-flow)
- Resolving merge conflicts (especially complex multi-file conflicts)
- Rebase workflows (interactive rebase, rebase onto, autosquash)
- Cherry-picking across branches
- Using git bisect to find bug-introducing commits
- Recovering lost work with reflog
- Monorepo git patterns (sparse checkout, subtree, submodules)
- Cleaning up messy git history
- Setting up git hooks for quality gates
- Force push safety and shared branch protocols
NOT for:
- GitHub Actions / CI/CD pipelines (use )
github-actions-pipeline-builder - PR review process and checklists (use )
code-review-checklist - GitHub API / webhooks / repository management
- Git LFS setup (mention it, but not the core focus)
适用场景:
- 为项目选择分支策略(Trunk-Based、GitHub Flow、Git-Flow)
- 解决合并冲突(尤其是复杂的多文件冲突)
- Rebase工作流(交互式rebase、rebase onto、autosquash)
- 跨分支执行cherry-pick
- 使用git bisect定位引入bug的提交
- 通过reflog恢复丢失的工作
- Monorepo Git模式(sparse checkout、subtree、submodules)
- 清理混乱的Git提交历史
- 设置Git钩子作为质量门禁
- 强制推送安全规范与共享分支协议
不适用场景:
- GitHub Actions / CI/CD流水线(请使用)
github-actions-pipeline-builder - PR评审流程与检查清单(请使用)
code-review-checklist - GitHub API / webhooks / 仓库管理
- Git LFS配置(可提及但非核心重点)
Core Decision: Branching Strategy
核心决策:分支策略
mermaid
flowchart TD
Start[New project or rethinking strategy?] --> Team{Team size?}
Team -->|Solo or 2-3| Trunk[Trunk-Based Development]
Team -->|4-15| GHFlow[GitHub Flow]
Team -->|15+ or regulated| Q2{Release cadence?}
Q2 -->|Continuous deploy| GHFlow
Q2 -->|Scheduled releases| GitFlow[Git-Flow]
Q2 -->|Multiple supported versions| GitFlow
Trunk --> T1[Main branch only]
T1 --> T2[Short-lived feature branches < 1 day]
T2 --> T3[Feature flags for incomplete work]
GHFlow --> G1[main + feature branches]
G1 --> G2[PR-based review]
G2 --> G3[Deploy from main after merge]
GitFlow --> GF1[main + develop + feature + release + hotfix]
GF1 --> GF2[Formal release branches]
GF2 --> GF3[Hotfix branches from main]mermaid
flowchart TD
Start[New project or rethinking strategy?] --> Team{Team size?}
Team -->|Solo or 2-3| Trunk[Trunk-Based Development]
Team -->|4-15| GHFlow[GitHub Flow]
Team -->|15+ or regulated| Q2{Release cadence?}
Q2 -->|Continuous deploy| GHFlow
Q2 -->|Scheduled releases| GitFlow[Git-Flow]
Q2 -->|Multiple supported versions| GitFlow
Trunk --> T1[Main branch only]
T1 --> T2[Short-lived feature branches < 1 day]
T2 --> T3[Feature flags for incomplete work]
GHFlow --> G1[main + feature branches]
G1 --> G2[PR-based review]
G2 --> G3[Deploy from main after merge]
GitFlow --> GF1[main + develop + feature + release + hotfix]
GF1 --> GF2[Formal release branches]
GF2 --> GF3[Hotfix branches from main]Strategy Comparison
策略对比
| Dimension | Trunk-Based | GitHub Flow | Git-Flow |
|---|---|---|---|
| Branch lifetime | Hours | Days | Days-weeks |
| Merge frequency | Multiple/day | Daily | Per-sprint |
| CI requirement | Mandatory | Strong | Optional |
| Rollback mechanism | Feature flags | Revert commit | Release branch |
| Best for | High-trust teams | Most web projects | Versioned releases |
| Worst for | Junior-heavy teams | Multiple live versions | Fast iteration |
| 维度 | Trunk-Based | GitHub Flow | Git-Flow |
|---|---|---|---|
| 分支生命周期 | 数小时 | 数天 | 数天至数周 |
| 合并频率 | 每日多次 | 每日一次 | 每迭代一次 |
| CI要求 | 强制 | 强烈建议 | 可选 |
| 回滚机制 | 功能开关 | 回退提交 | 发布分支 |
| 最佳适用场景 | 高信任团队 | 多数Web项目 | 版本化发布 |
| 最差适用场景 | 新手占比高的团队 | 多版本并行的项目 | 快速迭代场景 |
Merge vs Rebase Decision
Merge vs Rebase决策
mermaid
flowchart TD
Q[Integrating changes?] --> Shared{Is the branch shared?}
Shared -->|Yes, others push to it| Merge[Use merge]
Shared -->|No, only me| Q2{Want clean history?}
Q2 -->|Yes| Rebase[Use rebase]
Q2 -->|No, preserve context| Merge
Rebase --> Q3{Long-lived branch?}
Q3 -->|Yes, many conflicts expected| RebaseOnto[Consider rebase --onto]
Q3 -->|No| RebaseSimple[Simple rebase]mermaid
flowchart TD
Q[Integrating changes?] --> Shared{Is the branch shared?}
Shared -->|Yes, others push to it| Merge[Use merge]
Shared -->|No, only me| Q2{Want clean history?}
Q2 -->|Yes| Rebase[Use rebase]
Q2 -->|No, preserve context| Merge
Rebase --> Q3{Long-lived branch?}
Q3 -->|Yes, many conflicts expected| RebaseOnto[Consider rebase --onto]
Q3 -->|No| RebaseSimple[Simple rebase]Anti-Pattern: Rebase Shared Branches
反模式:对共享分支执行Rebase
Novice: "I'll rebase main into the shared feature branch to keep it clean."
Expert: Never rebase branches others are pushing to. Rebase rewrites commit SHAs — anyone who already pulled will get duplicate commits and merge hell. Use for shared branches, for personal branches.
Detection: Multiple developers report "weird duplicate commits" after a pull.
mergerebase新手: "我要把main分支rebase到共享功能分支上,保持历史整洁。"
专家: 绝不可以对其他人正在推送的分支执行rebase。Rebase会重写提交SHA——任何已经拉取过该分支的人都会遇到重复提交和合并灾难。共享分支使用,个人分支使用。
识别迹象: 多名开发者拉取后报告出现“奇怪的重复提交”。
mergerebaseAnti-Pattern: Merge Commit Soup
反模式:合并提交泛滥
Novice: "I'll just merge main into my feature branch every morning to stay current."
Expert: Daily merge commits from main create an unreadable history. Instead: on your personal branch (one clean operation), or if you must merge, at least squash when merging back to main.
Timeline: Before 2020, merge was the default. Modern teams prefer rebase for feature branches, merge (or squash-merge) for PRs.
git rebase main新手: "我每天早上都把main分支merge到我的功能分支上,保持同步。"
专家: 每天从main分支合并会产生难以阅读的提交历史。正确做法:在个人分支上执行(一次整洁的操作);如果必须合并,至少在合并回main时执行squash。
时间线: 2020年之前,merge是默认操作。现代团队更倾向于对功能分支使用rebase,对PR使用merge(或squash-merge)。
git rebase mainConflict Resolution
冲突解决
The Calm Approach
冷静处理法
bash
undefinedbash
undefined1. Before resolving: understand what happened
1. 解决前:了解冲突原因
git log --merge --oneline # Show conflicting commits
git diff --name-only --diff-filter=U # List conflicted files
git log --merge --oneline # 显示产生冲突的提交
git diff --name-only --diff-filter=U # 列出冲突文件
2. For each file: understand both sides
2. 针对每个文件:理解双方改动
git diff :2:file :3:file # :2 = ours, :3 = theirs
git diff :2:file :3:file # :2 = 本地版本, :3 = 远程版本
3. Resolve, then verify
3. 解决冲突后验证
git add resolved-file.ts
git diff --cached # Review what you're about to commit
git add resolved-file.ts
git diff --cached # 检查即将提交的内容
4. After all files resolved
4. 所有文件解决完成后
git merge --continue # or git rebase --continue
undefinedgit merge --continue # 或 git rebase --continue
undefinedAnti-Pattern: Accept Ours/Theirs Blindly
反模式:盲目接受本地/远程版本
Novice: "This conflict is too complex, I'll just and be done."
Expert: Blindly accepting one side loses the other person's work. If a conflict is genuinely too complex, use a 3-way merge tool () to see base + ours + theirs simultaneously. For large-scale conflicts, consider (reuse recorded resolution) to cache conflict solutions.
Detection: Features mysteriously disappear after merges.
git checkout --ours .git mergetoolrerere新手: "这个冲突太复杂了,我直接执行完事。"
专家: 盲目接受某一方会丢失另一方的工作。如果冲突确实复杂,使用三方合并工具()同时查看基础版本+本地版本+远程版本。对于大规模冲突,可考虑使用(复用已记录的冲突解决方案)来缓存解决方法。
识别迹象: 合并后功能神秘消失。
git checkout --ours .git mergetoolrerereAdvanced Operations
高级操作
Cherry-Pick Workflow
Cherry-Pick工作流
bash
undefinedbash
undefinedPick a specific commit from another branch
从其他分支选取特定提交
git cherry-pick abc123
git cherry-pick abc123
Pick a range (exclusive start, inclusive end)
选取一段范围(起始提交不包含,结束提交包含)
git cherry-pick abc123..def456
git cherry-pick abc123..def456
Cherry-pick without committing (stage only)
选取提交但不自动提交(仅暂存)
git cherry-pick --no-commit abc123
git cherry-pick --no-commit abc123
If conflicts: resolve then
如果出现冲突:解决后执行
git cherry-pick --continue
**When to cherry-pick**: Hotfixes that need to go to multiple release branches. Bug fixes from a feature branch that's not ready to merge.
**When NOT to**: If you need many commits, merge or rebase instead. Cherry-pick creates duplicate commits with different SHAs.git cherry-pick --continue
**适用场景**: 需要推送到多个发布分支的热修复,以及尚未准备好合并的功能分支中的bug修复。
**不适用场景**: 如果需要选取多个提交,使用merge或rebase替代。Cherry-pick会创建具有不同SHA的重复提交。Git Bisect (Find Bug-Introducing Commit)
Git Bisect(定位引入bug的提交)
bash
undefinedbash
undefinedStart bisect
启动bisect
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.2.0 # This tag was working
git bisect start
git bisect bad # 当前提交存在bug
git bisect good v1.2.0 # 该版本是正常的
Git checks out a middle commit. Test it, then:
Git会检出中间提交。测试后执行:
git bisect good # or: git bisect bad
git bisect good # 或: git bisect bad
Repeat until git identifies the first bad commit
重复直到Git定位到第一个有bug的提交
Automated bisect with a test script:
使用测试脚本自动执行bisect:
git bisect start HEAD v1.2.0
git bisect run npm test # Runs test at each step automatically
undefinedgit bisect start HEAD v1.2.0
git bisect run npm test # 在每个步骤自动运行测试
undefinedReflog Recovery (Undo Almost Anything)
Reflog恢复(几乎可以撤销任何操作)
bash
undefinedbash
undefinedSee recent HEAD positions
查看最近的HEAD位置
git reflog --oneline -20
git reflog --oneline -20
Recover a dropped stash
恢复已丢弃的stash
git stash list # Empty? Check reflog:
git fsck --no-reflogs | grep commit # Find dangling commits
git show <sha> # Inspect to find your stash
git stash list # 为空?查看reflog:
git fsck --no-reflogs | grep commit # 查找悬空提交
git show <sha> # 检查找到你的stash
Undo a bad rebase
撤销错误的rebase
git reflog
git reflog
Find the SHA before the rebase started
找到rebase开始前的SHA
git reset --hard HEAD@{5} # Reset to that point
git reset --hard HEAD@{5} # 重置到该节点
Recover deleted branch
恢复已删除的分支
git reflog | grep "branch-name"
git checkout -b recovered-branch <sha>
undefinedgit reflog | grep "branch-name"
git checkout -b recovered-branch <sha>
undefinedInteractive Rebase (Clean History)
交互式Rebase(清理提交历史)
bash
undefinedbash
undefinedRewrite last 5 commits
重写最近5个提交
git rebase -i HEAD~5
git rebase -i HEAD~5
In the editor:
在编辑器中:
pick abc123 Add user model ← keep as-is
pick abc123 Add user model ← 保留原样
squash def456 Fix typo in user model ← squash into previous
squash def456 Fix typo in user model ← 合并到上一个提交
reword ghi789 Add auth ← edit commit message
reword ghi789 Add auth ← 修改提交信息
drop jkl012 WIP debugging ← remove entirely
drop jkl012 WIP debugging ← 完全删除
edit mno345 Add migration ← pause to amend
edit mno345 Add migration ← 暂停以修改提交
Autosquash: commits prefixed with "fixup!" or "squash!" auto-arrange
Autosquash:前缀为"fixup!"或"squash!"的提交会自动合并
git commit --fixup abc123 # Creates "fixup! Add user model"
git rebase -i --autosquash HEAD~5 # Automatically squashes it
---git commit --fixup abc123 # 创建"fixup! Add user model"提交
git rebase -i --autosquash HEAD~5 # 自动合并该提交
---Monorepo Git Patterns
Monorepo Git模式
Sparse Checkout (Work on Subset)
Sparse Checkout(仅处理子集)
bash
undefinedbash
undefinedEnable sparse checkout
启用sparse checkout
git sparse-checkout init --cone
git sparse-checkout set packages/core packages/cli
git sparse-checkout init --cone
git sparse-checkout set packages/core packages/cli
Now only packages/core and packages/cli are checked out
现在仅packages/core和packages/cli被检出
Other directories exist in git but aren't on disk
其他目录存在于Git中但不会出现在磁盘上
undefinedundefinedSubtree (Embed Another Repo)
Subtree(嵌入其他仓库)
bash
undefinedbash
undefinedAdd a subtree
添加subtree
git subtree add --prefix=libs/shared https://github.com/org/shared.git main --squash
git subtree add --prefix=libs/shared https://github.com/org/shared.git main --squash
Pull updates
拉取更新
git subtree pull --prefix=libs/shared https://github.com/org/shared.git main --squash
git subtree pull --prefix=libs/shared https://github.com/org/shared.git main --squash
Push changes back upstream
将改动推回上游
git subtree push --prefix=libs/shared https://github.com/org/shared.git feature-x
undefinedgit subtree push --prefix=libs/shared https://github.com/org/shared.git feature-x
undefinedSubmodules vs Subtree
Submodules vs Subtree对比
| Dimension | Submodules | Subtree |
|---|---|---|
| Model | Pointer to external repo | Copy of external repo |
| Clone | Requires | Just works |
| Update | | |
| CI complexity | Higher (need init step) | Lower |
| Best for | Large vendored deps | Small shared libs |
| Footgun risk | High (detached HEAD trap) | Low |
| 维度 | Submodules | Subtree |
|---|---|---|
| 模式 | 指向外部仓库的指针 | 外部仓库的副本 |
| 克隆 | 需要 | 直接可用 |
| 更新 | | |
| CI复杂度 | 较高(需要初始化步骤) | 较低 |
| 最佳适用场景 | 大型依赖库 | 小型共享库 |
| 风险 | 高(分离HEAD陷阱) | 低 |
Git Hooks for Quality
Git钩子用于质量管控
bash
undefinedbash
undefined.git/hooks/pre-commit (or use husky/lefthook)
.git/hooks/pre-commit(或使用husky/lefthook)
#!/bin/sh
#!/bin/sh
Run linter on staged files only
仅对暂存文件运行检查
npx lint-staged
npx lint-staged
.git/hooks/commit-msg
.git/hooks/commit-msg
#!/bin/sh
#!/bin/sh
Enforce conventional commits
强制遵循规范提交格式
if ! grep -qE "^(feat|fix|docs|style|refactor|test|chore)((.+))?: .+" "$1"; then
echo "Commit message must follow Conventional Commits format"
exit 1
fi
if ! grep -qE "^(feat|fix|docs|style|refactor|test|chore)((.+))?: .+" "$1"; then
echo "提交信息必须遵循Conventional Commits格式"
exit 1
fi
.git/hooks/pre-push
.git/hooks/pre-push
#!/bin/sh
#!/bin/sh
Run tests before push
推送前运行测试
npm test || exit 1
undefinednpm test || exit 1
undefinedAnti-Pattern: Skipping Hooks
反模式:跳过钩子
Novice: "The pre-commit hook is slow, I'll just ."
Expert: If hooks are too slow, fix the hooks (use lint-staged for incremental linting, parallelize tests). becomes a habit that defeats the purpose. If you truly need to skip once (emergency hotfix), document why in the commit message.
--no-verify--no-verify新手: "pre-commit钩子太慢了,我直接用跳过。"
专家: 如果钩子太慢,应该优化钩子(使用lint-staged增量检查、并行化测试)。会变成习惯,失去钩子的意义。如果确实需要跳过一次(紧急热修复),请在提交信息中说明原因。
--no-verify--no-verifyBranching Strategy Selection Logic
分支策略选择逻辑
When the user asks which branching strategy to use, apply these rules in order:
当用户询问应使用哪种分支策略时,按以下顺序应用规则:
Hard constraints (override everything)
硬性约束(优先级最高)
-
Multi-version library (AND
hasMultipleVersions: true) → git-flowisLibrary: true- Reasoning: Maintaining v2.x hotfixes while developing v3.x requires long-lived release branches. Trunk-based cannot serve two audiences.
- Migration from trunk-based: Create branches from the last tag on each major. Backport via cherry-pick.
release/vN.x
-
Regulated industry () → git-flow
isRegulated: true- Reasoning: Auditors expect named release branches with approval gates, a clear trail from commit to production, and the ability to point at a branch and say "this is what shipped." Trunk-based can technically satisfy this with tags, but the audit conversation is easier with git-flow.
- Note: If CI maturity is high AND the compliance team is open to it, trunk-based with deploy tags + signed commits is superior. But assume the compliance team is not open to it.
-
多版本库 (AND
hasMultipleVersions: true) → Git-FlowisLibrary: true- 理由:维护v2.x热修复的同时开发v3.x需要长期存在的发布分支。Trunk-Based无法同时服务两类用户。
- 从Trunk-Based迁移:从每个主版本的最后一个标签创建分支,通过cherry-pick向后移植改动。
release/vN.x
-
受监管行业 () → Git-Flow
isRegulated: true- 理由:审计人员需要带有审批门禁的命名发布分支,清晰的从提交到生产的追踪路径,以及能够指向分支说明“这就是上线版本”的能力。Trunk-Based通过标签技术上可以满足,但Git-Flow更便于审计沟通。
- 注意:如果CI成熟度高且合规团队接受,带有部署标签+签名提交的Trunk-Based更优。但默认假设合规团队不接受。
CI maturity gate
CI成熟度门槛
- Low CI maturity () → github-flow
ciMaturity: 'low'- Reasoning: Trunk-based without comprehensive CI means broken code on main. GitHub Flow (feature branches + PR review + merge) provides a human safety net. Recommend investing in CI, then graduating to trunk-based.
- Migration to trunk-based later: Shorten branch lifetimes to <1 day, add branch protection requiring green CI, then drop the requirement for PR approval on small changes.
- 低CI成熟度 () → GitHub Flow
ciMaturity: 'low'- 理由:没有完善CI的Trunk-Based会导致main分支出现损坏代码。GitHub Flow(功能分支+PR评审+合并)提供人工安全网。建议先投入CI建设,再升级到Trunk-Based。
- 后续迁移到Trunk-Based:将分支生命周期缩短至<1天,添加分支保护要求CI通过,然后取消小改动的PR审批要求。
Default (most teams)
默认规则(大多数团队)
- Everything else → trunk-based
- Reasoning: Smallest feedback loops, least merge pain, forces good CI habits. Feature flags handle incomplete work. Short-lived branches (<1 day) are acceptable as a concession.
- If team is >15 people: Consider trunk-based with short-lived feature branches (still trunk-based — the branch lives <24h and auto-deletes after merge).
- 其他所有情况 → Trunk-Based
- 理由:反馈循环最短,合并痛苦最少,强制养成良好的CI习惯。功能开关处理未完成的工作。可接受短生命周期分支(<1天)作为折中方案。
- 如果团队人数>15人:考虑使用带有短生命周期功能分支的Trunk-Based(仍属于Trunk-Based——分支存在时间<24小时,合并后自动删除)。
Migration paths
迁移路径
| From | To | Steps |
|---|---|---|
| git-flow → trunk-based | 1. Merge | |
| git-flow → github-flow | 1. Merge | |
| github-flow → trunk-based | 1. Reduce PR size to <200 lines. 2. Add comprehensive CI. 3. Allow direct push to |
| 从 | 到 | 步骤 |
|---|---|---|
| Git-Flow → Trunk-Based | 1. 将 | |
| Git-Flow → GitHub Flow | 1. 将 | |
| GitHub Flow → Trunk-Based | 1. 将PR大小缩减至<200行。2. 完善CI体系。3. 允许对微小改动直接推送到 |
Force Push Safety
强制推送安全规范
bash
undefinedbash
undefinedNEVER force push to main/master
绝不要对main/master分支执行强制推送
Use --force-with-lease instead of --force
使用--force-with-lease替代--force
git push --force-with-lease origin feature-branch
git push --force-with-lease origin feature-branch
--force-with-lease checks that remote hasn't been updated
--force-with-lease会检查远程分支自上次拉取后是否有更新
since your last fetch. Prevents overwriting others' work.
防止覆盖他人的工作
Set as default (never use bare --force again):
设置为默认(永远不要使用裸--force):
git config --global alias.pushf "push --force-with-lease"
---git config --global alias.pushf "push --force-with-lease"
---References
参考资料
- — Consult for complex rebase scenarios: rebase --onto, interactive rebase strategies, handling rebase conflicts in long-lived branches
references/advanced-rebase-patterns.md - — Consult for monorepo-specific patterns: sparse checkout optimization, CODEOWNERS, path-based CI triggers, large repo performance
references/monorepo-git-strategies.md
- — 复杂rebase场景参考:rebase --onto、交互式rebase策略、处理长生命周期分支的rebase冲突
references/advanced-rebase-patterns.md - — Monorepo专属模式参考:sparse checkout优化、CODEOWNERS、基于路径的CI触发、大型仓库性能优化
references/monorepo-git-strategies.md