关于 git-workflow-expert
面向开发者的 Git 工作流技能,涵盖分支策略选择、冲突处理、工作恢复及高级仓库操作。
主要功能
- 01选择分支策略
- 02合并与变基指导
- 03冲突解决方法
- 04使用 reflog 恢复提交
- 05单体仓库模式与 Git hooks
适用场景
- 01为团队选择分支模型
- 02解决复杂的多文件冲突
- 03恢复丢失的提交或暂存
- 04管理稀疏检出或子模块
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ curiositech/ some_claude_skills --skill git-workflow-expert安装后在 Claude Code 中输入/git-workflow-expert确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.claude-plugin/plugin.jsonreferences/advanced-rebase-patterns.mdmonorepo-git-strategies.md详细介绍
Git 工作流专家
掌握从日常工作流到灾难恢复的 Git 操作。涵盖分支策略、合并与变基的选择、冲突解决、单体仓库模式,以及大多数开发者从未学过、却迫切需要掌握的高级操作。
适用场景
适用于:
- 为项目选择分支策略(trunk-based、GitHub Flow、git-flow)
- 解决合并冲突(尤其是复杂的多文件冲突)
- 变基工作流(交互式变基、变基到指定分支、自动压缩)
- 在分支之间挑选提交
- 使用 git bisect 查找引入 Bug 的提交
- 使用 reflog 恢复丢失的工作
- 单体仓库 Git 模式(稀疏检出、子树、子模块)
- 整理混乱的 Git 历史记录
- 设置 Git 钩子作为质量门禁
- 安全强制推送和共享分支协议
不适用于:
- GitHub Actions / CI/CD 流水线(使用
github-actions-pipeline-builder) - PR 审查流程和清单(使用
code-review-checklist) - GitHub API / Webhook / 仓库管理
- Git LFS 设置(会提及,但不是重点)
核心决策:分支策略
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]
策略对比
| 维度 | 主干开发 | GitHub Flow | Git-Flow |
|---|---|---|---|
| 分支生命周期 | 数小时 | 数天 | 数天至数周 |
| 合并频率 | 每天多次 | 每天 | 每个迭代一次 |
| CI 要求 | 必须 | 强烈建议 | 可选 |
| 回滚机制 | 功能开关 | 回退提交 | 发布分支 |
| 最适合 | 高信任度团队 | 大多数 Web 项目 | 有版本化发布的项目 |
| 最不适合 | 初级开发者居多的团队 | 同时维护多个线上版本的项目 | 快速迭代 |
合并还是变基:如何选择
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]
反模式:对共享分支进行变基
新手:“我会把 main 变基到共享功能分支上,让历史保持整洁。”
专家:绝不要对他人也在推送的分支进行变基。变基会改写提交 SHA,已经拉取过该分支的人会遇到重复提交和合并混乱。共享分支使用 merge,个人分支使用 rebase。
识别方式:多名开发者在拉取后报告“出现奇怪的重复提交”。
反模式:合并提交泛滥
新手:“我每天早上都会把 main 合并到自己的功能分支,以保持同步。”
专家:每天从 main 合并都会产生大量合并提交,让历史记录难以阅读。更好的做法是:在个人分支上运行 git rebase main(一次干净的操作);如果必须合并,至少在合并回 main 时使用压缩合并。
时间线:2020 年之前,合并是默认做法。现代团队更倾向于对功能分支使用变基,对 PR 使用合并(或压缩合并)。
冲突解决
冷静处理
# 1. Before resolving: understand what happened
git log --merge --oneline # Show conflicting commits
git diff --name-only --diff-filter=U # List conflicted files
# 2. For each file: understand both sides
git diff :2:file :3:file # :2 = ours, :3 = theirs
# 3. Resolve, then verify
git add resolved-file.ts
git diff --cached # Review what you're about to commit
# 4. After all files resolved
git merge --continue # or git rebase --continue
反模式:盲目接受 Ours/Theirs
新手:“这个冲突太复杂了,我直接运行 git checkout --ours . 就解决了。”
专家:盲目接受任一方的更改会丢失另一方的工作。如果冲突确实太复杂,请使用三方合并工具(git mergetool)同时查看 base、ours 和 theirs。对于大规模冲突,可以考虑使用 rerere(重用已记录的解决方案)缓存冲突解决方案。
识别方式:合并后功能莫名其妙地消失了。
高级操作
Cherry-pick 工作流
# Pick a specific commit from another branch
git cherry-pick abc123
# Pick a range (exclusive start, inclusive end)
git cherry-pick abc123..def456
# Cherry-pick without committing (stage only)
git cherry-pick --no-commit abc123
# If conflicts: resolve then
git cherry-pick --continue
适合使用 cherry-pick 的场景:需要移植到多个发布分支的紧急修复。来自尚未准备好合并的功能分支的 Bug 修复。
不适合的场景:需要处理多个提交时,应改用合并或变基。Cherry-pick 会创建 SHA 不同的重复提交。
Git Bisect(查找引入 Bug 的提交)
# Start bisect
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.2.0 # This tag was working
# Git checks out a middle commit. Test it, then:
git bisect good # or: git bisect bad
# Repeat until git identifies the first bad commit
# Automated bisect with a test script:
git bisect start HEAD v1.2.0
git bisect run npm test # Runs test at each step automatically
Reflog 恢复(几乎可以撤销任何操作)
# See recent HEAD positions
git reflog --oneline -20
# Recover a dropped stash
git stash list # Empty? Check reflog:
git fsck --no-reflogs | grep commit # Find dangling commits
git show <sha> # Inspect to find your stash
# Undo a bad rebase
git reflog
# Find the SHA before the rebase started
git reset --hard HEAD@{5} # Reset to that point
# Recover deleted branch
git reflog | grep "branch-name"
git checkout -b recovered-branch <sha>
交互式变基(整理历史记录)
# Rewrite last 5 commits
git rebase -i HEAD~5
# In the editor:
# pick abc123 Add user model ← keep as-is
# squash def456 Fix typo in user model ← squash into previous
# reword ghi789 Add auth ← edit commit message
# drop jkl012 WIP debugging ← remove entirely
# edit mno345 Add migration ← pause to amend
# Autosquash: commits prefixed with "fixup!" or "squash!" auto-arrange
git commit --fixup abc123 # Creates "fixup! Add user model"
git rebase -i --autosquash HEAD~5 # Automatically squashes it
单体仓库 Git 模式
稀疏检出(处理部分目录)
# Enable sparse checkout
git sparse-checkout init --cone
git sparse-checkout set packages/core packages/cli
# Now only packages/core and packages/cli are checked out
# Other directories exist in git but aren't on disk
子树(嵌入另一个仓库)
# Add a subtree
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
# Push changes back upstream
git subtree push --prefix=libs/shared https://github.com/org/shared.git feature-x
子模块与子树
| 维度 | 子模块 | 子树 |
|---|---|---|
| 模型 | 指向外部仓库的指针 | 外部仓库的副本 |
| 克隆 | 需要 --recurse-submodules | 开箱即用 |
| 更新 | git submodule update | git subtree pull |
| CI 复杂度 | 较高(需要初始化步骤) | 较低 |
| 最适合 | 大型供应商依赖 | 小型共享库 |
| 踩坑风险 | 高(分离 HEAD 陷阱) | 低 |
用于保障质量的 Git 钩子
# .git/hooks/pre-commit (or use husky/lefthook)
#!/bin/sh
# Run linter on staged files only
npx lint-staged
# .git/hooks/commit-msg
#!/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
# .git/hooks/pre-push
#!/bin/sh
# Run tests before push
npm test || exit 1
反模式:跳过钩子
新手:「pre-commit 钩子太慢了,我就用 --no-verify 跳过吧。」
专家:如果钩子太慢,就优化钩子(使用 lint-staged 进行增量 lint,并行运行测试)。--no-verify 会变成一种习惯,让钩子失去意义。如果确实需要跳过一次(紧急热修复),请在提交消息中说明原因。
分支策略选择逻辑
当用户询问该采用哪种分支策略时,按以下顺序应用这些规则:
硬性约束(优先于其他所有规则)
-
多版本库(
hasMultipleVersions: true且isLibrary: true)→ git-flow- 原因:在开发 v3.x 的同时维护 v2.x 热修复,需要长期存在的发布分支。Trunk-based 无法同时服务两类用户。
- 从 trunk-based 迁移:从各个主版本的最后一个标签创建
release/vN.x分支。通过 cherry-pick 回移更改。
-
受监管行业(
isRegulated: true)→ git-flow- 原因:审计人员期望有具名发布分支和审批关卡、从提交到生产环境的清晰追溯路径,以及能够指向某个分支并说明「这就是已发布的内容」。Trunk-based 在技术上可以通过标签满足这些要求,但采用 git-flow 更容易应对审计。
- 注意:如果 CI 成熟度高,并且合规团队愿意接受,采用部署标签和签名提交的 trunk-based 会更好。但请假设合规团队不愿意接受。
CI 成熟度门槛
- CI 成熟度低(
ciMaturity: 'low')→ github-flow- 原因:没有全面的 CI,trunk-based 会导致 main 上出现损坏的代码。GitHub Flow(功能分支 + PR 审查 + 合并)提供了人工安全保障。建议投入资源完善 CI,然后再升级到 trunk-based。
- 之后迁移到 trunk-based:将分支生命周期缩短至 <1 天,添加要求 CI 检查通过的分支保护,然后取消小改动必须经过 PR 审批的要求。
默认策略(适用于大多数团队)
- 其他所有情况 → trunk-based
- 原因:反馈周期最短、合并痛苦最少,并能促使团队养成良好的 CI 习惯。功能标志可处理尚未完成的工作。短期分支(<1 天)可以作为一种妥协。
- 如果团队人数 >15:考虑采用带有短期功能分支的 trunk-based(仍属于 trunk-based——分支生命周期 <24h,合并后自动删除)。
迁移路径
| 从 | 到 | 步骤 |
|---|---|---|
| git-flow → trunk-based | 1. 将 develop 合并到 main。 2. 删除 develop。 3. 在 main 上设置分支保护(要求 CI 检查通过)。 4. 使用功能标志处理尚未完成的工作。 5. 将分支生命周期目标缩短至 <1 天。 | |
| git-flow → github-flow | 1. 将 develop 合并到 main。 2. 删除 develop 和所有 release/* 分支。 3. 直接向 main 提交 PR。 4. 从 main 创建发布标签。 | |
| github-flow → trunk-based | 1. 将 PR 大小缩减至 <200 行。 2. 添加全面的 CI。 3. 允许对简单改动直接推送到 main。 4. 较大的改动仍使用 PR,但在当天合并。 |
强制推送安全
# NEVER force push to main/master
# Use --force-with-lease instead of --force
git push --force-with-lease origin feature-branch
# --force-with-lease checks that remote hasn't been updated
# since your last fetch. Prevents overwriting others' work.
# Set as default (never use bare --force again):
git config --global alias.pushf "push --force-with-lease"
参考资料
references/advanced-rebase-patterns.md— 复杂变基场景请参阅此文档:rebase --onto、交互式变基策略、处理长期分支中的变基冲突references/monorepo-git-strategies.md— monorepo 特有模式请参阅此文档:稀疏检出优化、CODEOWNERS、基于路径的 CI 触发器、大型仓库性能