Git Workflows
Advanced git operations for real-world development. Covers interactive rebase, bisect, worktree, reflog recovery, subtrees, submodules, sparse checkout, conflict resolution, and monorepo patterns.
When to Use
- - Cleaning up commit history before merging (interactive rebase)
- Finding which commit introduced a bug (bisect)
- Working on multiple branches simultaneously (worktree)
- Recovering lost commits or undoing mistakes (reflog)
- Managing shared code across repos (subtree/submodule)
- Resolving complex merge conflicts
- Cherry-picking commits across branches or forks
- Working with large monorepos (sparse checkout)
Interactive Rebase
Squash, reorder, edit commits
CODEBLOCK0
The editor opens with a pick list:
CODEBLOCK1
Commands available:
CODEBLOCK2
Common patterns
CODEBLOCK3
Autosquash (commit messages that auto-arrange)
CODEBLOCK4
Abort or continue
CODEBLOCK5
Bisect (Find the Bug)
Binary search through commits
CODEBLOCK6
Automated bisect (with a test script)
CODEBLOCK7
Bisect with build failures
CODEBLOCK8
Worktree (Parallel Branches)
Work on multiple branches simultaneously
CODEBLOCK9
Use cases
CODEBLOCK10
Reflog (Recovery)
See everything git remembers
CODEBLOCK11
Recover from mistakes
CODEBLOCK12
Cherry-Pick
Copy specific commits to another branch
CODEBLOCK13
Handle conflicts during cherry-pick
CODEBLOCK14
Subtree and Submodule
Subtree (simpler — copies code into your repo)
CODEBLOCK15
Submodule (pointer to another repo at a specific commit)
CODEBLOCK16
When to use which
CODEBLOCK17
Sparse Checkout (Monorepo)
Check out only the directories you need
CODEBLOCK18
Clone with sparse checkout (large monorepos)
CODEBLOCK19
Conflict Resolution
Understand the conflict markers
CODEBLOCK20
Resolution strategies
CODEBLOCK21
Rebase conflict workflow
CODEBLOCK22
Rerere (reuse recorded resolutions)
CODEBLOCK23
Stash Patterns
CODEBLOCK24
Blame and Log Archaeology
CODEBLOCK25
Tags and Releases
CODEBLOCK26
Tips
- -
git rebase -i is the single most useful advanced git command. Learn it first. - Never rebase commits that have been pushed to a shared branch. Rebase your local/feature work only.
- INLINECODE1 is your safety net. If you lose commits, they're almost always recoverable within 90 days.
- INLINECODE2 with an automated test is faster than manual binary search and eliminates human error.
- Worktrees are cheaper than multiple clones — they share
.git storage. - Prefer
git subtree over git submodule unless you have a specific reason. Subtrees are simpler for collaborators. - Enable
rerere globally. It remembers conflict resolutions so you never solve the same conflict twice. - INLINECODE7 is much better than bare
git stash. You'll thank yourself when you have 5 stashes. - INLINECODE9 (pickaxe) is the fastest way to find when a function or variable was added or removed.
Git 工作流
面向实际开发的高级 Git 操作。涵盖交互式变基、二分查找、工作树、引用日志恢复、子树、子模块、稀疏检出、冲突解决和单体仓库模式。
使用场景
- - 合并前清理提交历史(交互式变基)
- 查找引入缺陷的提交(二分查找)
- 同时处理多个分支(工作树)
- 恢复丢失的提交或撤销错误(引用日志)
- 跨仓库管理共享代码(子树/子模块)
- 解决复杂的合并冲突
- 跨分支或复刻挑选提交
- 处理大型单体仓库(稀疏检出)
交互式变基
压缩、重排、编辑提交
bash
交互式变基最近5个提交
git rebase -i HEAD~5
变基到主分支(从分叉点开始的所有提交)
git rebase -i main
编辑器打开后显示选择列表:
pick a1b2c3d 添加用户模型
pick e4f5g6h 修复用户模型中的拼写错误
pick i7j8k9l 添加用户控制器
pick m0n1o2p 添加用户路由
pick q3r4s5t 修复控制器中的导入
可用命令:
pick = 原样使用提交
reword = 使用提交但编辑提交信息
edit = 在此提交后停止以修改它
squash = 合并到前一个提交(保留两条提交信息)
fixup = 合并到前一个提交(丢弃此提交信息)
drop = 完全移除该提交
常见模式
bash
将修复提交压缩到其父提交中
将修复提交的pick改为fixup:
pick a1b2c3d 添加用户模型
fixup e4f5g6h 修复用户模型中的拼写错误
pick i7j8k9l 添加用户控制器
fixup q3r4s5t 修复控制器中的导入
pick m0n1o2p 添加用户路由
重排提交(只需移动行)
pick i7j8k9l 添加用户控制器
pick m0n1o2p 添加用户路由
pick a1b2c3d 添加用户模型
将一个提交拆分为两个
标记为edit,然后当它停止时:
git reset HEAD~
git add src/model.ts
git commit -m 添加用户模型
git add src/controller.ts
git commit -m 添加用户控制器
git rebase --continue
自动压缩(自动排列的提交信息)
bash
提交修复时,引用要压缩到的目标提交
git commit --fixup=a1b2c3d -m 修复拼写错误
或
git commit --squash=a1b2c3d -m 额外更改
稍后,使用自动压缩进行变基
git rebase -i --autosquash main
fixup/squash 提交会自动放置在其目标之后
中止或继续
bash
git rebase --abort # 取消并恢复原始状态
git rebase --continue # 解决冲突或编辑后继续
git rebase --skip # 跳过当前提交并继续
二分查找(查找缺陷)
在提交中进行二分搜索
bash
开始二分查找
git bisect start
标记当前提交为坏(存在缺陷)
git bisect bad
标记一个已知的好提交(缺陷出现之前)
git bisect good v1.2.0
或:git bisect good abc123
Git 检出一个中间提交。测试它,然后:
git bisect good # 如果此提交没有缺陷
git bisect bad # 如果此提交有缺陷
重复直到 Git 识别出确切的提交
abc123 是第一个坏提交
完成 — 返回原始分支
git bisect reset
自动二分查找(使用测试脚本)
bash
全自动:Git 在每个提交上运行脚本
脚本必须为好时退出0,为坏时退出1
git bisect start HEAD v1.2.0
git bisect run ./test-for-bug.sh
示例测试脚本
cat > /tmp/test-for-bug.sh << EOF
#!/bin/bash
如果缺陷不存在返回0,如果存在返回1
npm test -- --grep 登录应重定向 2>/dev/null
EOF
chmod +x /tmp/test-for-bug.sh
git bisect run /tmp/test-for-bug.sh
处理构建失败的二分查找
bash
如果提交无法编译,跳过它
git bisect skip
跳过已知损坏的提交范围
git bisect skip v1.3.0..v1.3.5
工作树(并行分支)
同时处理多个分支
bash
为不同分支添加工作树
git worktree add ../myproject-hotfix hotfix/urgent-fix
创建一个新目录,其中检出了该分支
使用新分支添加工作树
git worktree add ../myproject-feature -b feature/new-thing
列出工作树
git worktree list
完成后移除工作树
git worktree remove ../myproject-hotfix
清理过时的工作树引用
git worktree prune
使用场景
bash
在保持当前工作不变的情况下审查PR
git worktree add ../review-pr-123 origin/pr-123
在功能分支上开发时在主分支上运行测试
git worktree add ../main-tests main
cd ../main-tests && npm test
并排比较分支之间的行为
git worktree add ../compare-old release/v1.0
git worktree add ../compare-new release/v2.0
引用日志(恢复)
查看 Git 记住的所有内容
bash
显示引用日志(所有HEAD移动)
git reflog
输出:
abc123 HEAD@{0}: commit: 添加功能
def456 HEAD@{1}: rebase: 移动到 main
ghi789 HEAD@{2}: checkout: 从 feature 移动到 main
显示特定分支的引用日志
git reflog show feature/my-branch
带时间戳显示
git reflog --date=relative
从错误中恢复
bash
撤销错误的变基(在引用日志中找到变基前的提交)
git reflog
找到:ghi789 HEAD@{5}: checkout: 从 feature 移动到 main(变基前)
git reset --hard ghi789
恢复已删除的分支
git reflog
找到该分支的最后一个提交
git branch recovered-branch abc123
在 reset --hard 后恢复
git reflog
git reset --hard HEAD@{2} # 回到2个引用日志条目之前
恢复已丢弃的贮藏
git fsck --unreachable | grep commit
或
git stash list # 如果它还在
git log --walk-reflogs --all -- stash # 找到已丢弃的贮藏提交
挑选提交
将特定提交复制到另一个分支
bash
挑选单个提交
git cherry-pick abc123
挑选多个提交
git cherry-pick abc123 def456 ghi789
挑选一个范围(排除起始,包含结束)
git cherry-pick abc123..ghi789
挑选但不提交(仅暂存更改)
git cherry-pick --no-commit abc123
从另一个远程/复刻挑选
git remote add upstream https://github.com/other/repo.git
git fetch upstream
git cherry-pick upstream/main~3 # 从上游主分支的第3个提交
处理挑选过程中的冲突
bash
如果出现冲突:
1. 解决文件中的冲突
2. 暂存已解决的文件
git add resolved-file.ts
3. 继续
git cherry-pick --continue
或中止
git cherry-pick --abort
子树和子模块
子树(更简单 — 将代码复制到你的仓库中)
bash
添加子树
git subtree add --prefix=lib/shared https://github.com/org/shared-lib.git main --squash
从上游拉取更新
git subtree pull --prefix=lib/shared https://github.com/org/shared-lib.git main --squash
将本地更改推送到上游
git subtree push --prefix=lib/shared https://github.com/org/shared-lib.git main
将子树拆分为自己的分支(用于提取)
git subtree split --prefix=lib/shared -b shared-lib-standalone
子模块(指向另一个仓库特定提交的指针)