Git Workflows

Polar Sponsor
爱发电 赞助
.NET 9.0

涉及 add/commit/push 之外的进阶 Git 操作。适用于变基、二分查找 Bug、使用工作树并行开发、利用 reflog 恢复、管理子树/子模块、解决合并冲突、跨分支拣选提交或处理单体仓库等场景。

Git Workflows. 高级Git操作,用于现实世界的发展.

功能概述

Git Workflows. 高级Git操作,用于现实世界的发展.是一项面向实际任务的技能,主要用于Covers 交互式重置基础,双节虫,工作树,reflog恢复,子树,子模块,稀疏的退货,冲突解决,以及。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。

核心要点

  • 使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。
  • 该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。
  • 从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。

使用与执行

实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。

结果检查与注意事项

执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。

Git 工作流

面向真实开发场景的高级 Git 操作。涵盖交互式变基(interactive rebase)、二分查找(bisect)、工作树(worktree)、引用日志恢复(reflog recovery)、子树(subtree)、子模块(submodule)、稀疏检出(sparse checkout)、冲突解决,以及单体仓库(monorepo)模式。

适用场景

  • 合并前清理提交历史(交互式变基)
  • 定位引入缺陷的具体提交(bisect)
  • 同时在多个分支上开展工作(worktree)
  • 恢复丢失的提交或撤销误操作(reflog)
  • 跨仓库管理共享代码(subtree / submodule)
  • 解决复杂的合并冲突
  • 在分支或 fork 之间挑选特定提交(cherry-pick)
  • 处理大型 monorepo(稀疏检出)

交互式变基

压缩、重排、编辑提交

# 交互式变基最近 5 次提交
git rebase -i HEAD~5

# 变基到 main 分支(自分叉以来的所有提交)
git rebase -i main

编辑器将打开一个可操作的提交列表:

pick a1b2c3d Add user model
pick e4f5g6h Fix typo in user model
pick i7j8k9l Add user controller
pick m0n1o2p Add user routes
pick q3r4s5t Fix import in controller

可用命令说明:

pick   = 保留该提交(不修改)
reword = 保留该提交,但编辑其提交信息
edit   = 在该提交后暂停,允许修改其内容
squash = 合并到前一个提交(保留两个提交信息)
fixup  = 合并到前一个提交(丢弃该提交的信息)
drop   = 完全移除该提交

常见模式

# 将修复类提交压缩进其父提交  
# 将修复提交的 "pick" 改为 "fixup":
pick a1b2c3d Add user model
fixup e4f5g6h Fix typo in user model
pick i7j8k9l Add user controller
fixup q3r4s5t Fix import in controller
pick m0n1o2p Add user routes

# 重排提交顺序(仅调整行顺序)
pick i7j8k9l Add user controller
pick m0n1o2p Add user routes
pick a1b2c3d Add user model

# 将一次提交拆分为两次  
# 标记为 "edit",当变基暂停时执行:
git reset HEAD~
git add src/model.ts
git commit -m "Add user model"
git add src/controller.ts
git commit -m "Add user controller"
git rebase --continue

自动压缩(autosquash:支持自动归位的提交信息)

# 提交修复时,引用目标提交以触发自动压缩
git commit --fixup=a1b2c3d -m "Fix typo"
# 或
git commit --squash=a1b2c3d -m "Additional changes"

# 后续执行带 autosquash 的变基
git rebase -i --autosquash main
# fixup / squash 类提交将被自动置于其目标提交之后

中止或继续变基

git rebase --abort      # 取消变基,恢复原始状态
git rebase --continue   # 解决冲突或完成编辑后继续
git rebase --skip       # 跳过当前提交并继续

二分查找(定位缺陷)

在提交历史中进行二分搜索

# 启动 bisect
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 is the first bad commit"

# 完成 — 返回原始分支
git bisect reset

自动化 bisect(配合测试脚本)

# 全自动模式: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 "login should redirect" 2>/dev/null
EOF
chmod +x /tmp/test-for-bug.sh
git bisect run /tmp/test-for-bug.sh

处理构建失败的提交

# 若某次提交无法编译,跳过它
git bisect skip

# 跳过一段已知不可用的提交范围
git bisect skip v1.3.0..v1.3.5

工作树(并行分支)

同时在多个分支上工作

# 为另一分支添加工作树
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

典型用例

# 在保持当前工作区不变的前提下审阅 PR
git worktree add ../review-pr-123 origin/pr-123

# 在 feature 分支开发的同时,在 main 分支上运行测试
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 记录的所有操作

# 显示 reflog(所有 HEAD 移动记录)
git reflog
# 输出示例:
# abc123 HEAD@{0}: commit: Add feature
# def456 HEAD@{1}: rebase: moving to main
# ghi789 HEAD@{2}: checkout: moving from feature to main

# 查看特定分支的 reflog
git reflog show feature/my-branch

# 显示带时间戳的 reflog
git reflog --date=relative

从误操作中恢复

# 撤销错误的变基(在 reflog 中找到变基前的提交)
git reflog
# 找到类似:"ghi789 HEAD@{5}: checkout: moving from feature to main"(变基前状态)
git reset --hard ghi789

# 恢复已被删除的分支
git reflog
# 找到该分支最后的提交哈希
git branch recovered-branch abc123

# 在执行了 git reset --hard 后恢复
git reflog
git reset --hard HEAD@{2}   # 回退至 reflog 中倒数第二个条目

# 恢复被丢弃的 stash
git fsck --unreachable | grep commit
# 或
git stash list  # 若 stash 仍存在
git log --walk-reflogs --all -- stash  # 查找被丢弃的 stash 提交

挑选提交(Cherry-Pick)

将特定提交复制到另一分支

# 挑选单个提交
git cherry-pick abc123

# 挑选多个提交
git cherry-pick abc123 def456 ghi789

# 挑选提交范围(起始提交不包含,结束提交包含)
git cherry-pick abc123..ghi789

# 仅暂存变更,不自动提交
git cherry-pick --no-commit abc123

# 从其他远程仓库或 fork 中挑选提交
git remote add upstream https://github.com/other/repo.git
git fetch upstream
git cherry-pick upstream/main~3   # 取 upstream 主干倒数第 3 个提交

处理 cherry-pick 过程中的冲突

# 若发生冲突:
# 1. 在文件中手动解决冲突
# 2. 将已解决的文件加入暂存区
git add resolved-file.ts
# 3. 继续 cherry-pick
git cherry-pick --continue

# 或中止操作
git cherry-pick --abort

子树与子模块

子树(更简单 —— 将代码复制进你的仓库)

# 添加子树
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

子模块(指向另一仓库特定提交的指针)

# 添加子模块
git submodule add https://github.com/org/shared-lib.git lib/shared

# 克隆含子模块的仓库
git clone --recurse-submodules https://github.com/org/main-repo.git

# 克隆后初始化子模块(若遗漏 --recurse 参数)
git submodule update --init --recursive

# 更新子模块至最新提交
git submodule update --remote

# 移除子模块
git rm lib/shared
rm -rf .git/modules/lib/shared
# 若 .gitmodules 中仍有残留条目,请手动删除

如何选择:子树 or 子模块?

子树:更简单,克隆者无需额外命令,代码直接存在于你的仓库中。  
      适用于:共享库、第三方代码、上游更新频率较低的场景。

子模块:精确指向某一提交,仓库体积更小,职责边界清晰。  
      适用于:大型依赖、拥有独立发布周期、多团队协作的场景。

稀疏检出(单体仓库)

仅检出所需目录

# 启用稀疏检出
git sparse-checkout init --cone

# 指定需检出的目录
git sparse-checkout set packages/my-app packages/shared-lib

# 新增一个目录
git sparse-checkout add packages/another-lib

# 查看当前已检出的内容
git sparse-checkout list

# 关闭稀疏检出(恢复检出全部内容)
git sparse-checkout disable

带稀疏检出的克隆(适用于大型 monorepo)

# 部分克隆 + 稀疏检出(超大仓库最快方式)
git clone --filter=blob:none --sparse https://github.com/org/monorepo.git
cd monorepo
git sparse-checkout set packages/my-service

# 无检出克隆(仅下载元数据)
git clone --no-checkout https://github.com/org/monorepo.git
cd monorepo
git sparse-checkout set packages/my-service
git checkout main

冲突解决

理解冲突标记

<<<<<<< HEAD (或 "ours")
当前分支上的修改
=======
来自待合并分支的修改
>>>>>>> feature-branch (或 "theirs")

解决策略

# 接受当前分支全部变更(当前分支获胜)
git checkout --ours path/to/file.ts
git add path/to/file.ts

# 接受待合并分支全部变更(待合并分支获胜)
git checkout --theirs path/to/file.ts
git add path/to/file.ts

# 对所有文件接受当前分支变更
git checkout --ours .
git add .

# 使用图形化合并工具
git mergetool

# 查看三方差异(共同祖先、当前分支、待合并分支)
git diff --cc path/to/file.ts

# 查看共同祖先版本
git show :1:path/to/file.ts   # 基础版本(共同祖先)
git show :2:path/to/file.ts   # 当前分支版本(ours)
git show :3:path/to/file.ts   # 待合并分支版本(theirs)

变基过程中的冲突处理流程

# 变基期间,冲突会逐个提交出现  
# 1. 在文件中修复冲突  
# 2. 暂存修复后的文件  
git add fixed-file.ts  
# 3. 继续处理下一个提交  
git rebase --continue  
# 4. 重复直到完成  

# 若某次提交在解决冲突后变为完全空提交  
git rebase --skip  

Rerere(复用已记录的冲突解决方案)

# 全局启用 rerere  
git config --global rerere.enabled true  

# Git 将记住你此前如何解决冲突  
# 下次相同冲突再次出现时,将自动应用历史方案  

# 查看已记录的解决方案  
ls .git/rr-cache/  

# 忘记某次错误的解决方案  
git rerere forget path/to/file.ts  

Stash 使用模式

# 带描述信息保存 stash  
git stash push -m "WIP: refactoring auth flow"  

# 仅暂存特定文件  
git stash push -m "partial stash" -- src/auth.ts src/login.ts  

# 暂存包括未跟踪文件在内的全部变更  
git stash push -u -m "with untracked"  

# 列出所有 stash  
git stash list  

# 应用最近一次 stash(保留在 stash 列表中)  
git stash apply  

# 应用并从 stash 列表中移除  
git stash pop  

# 应用指定 stash  
git stash apply stash@{2}  

# 查看某次 stash 的具体内容  
git stash show -p stash@{0}  

# 从 stash 创建新分支  
git stash branch new-feature stash@{0}  

# 删除指定 stash  
git stash drop stash@{1}  

# 清空所有 stash  
git stash clear  

追溯 blame 与日志考古

# 查看每行代码由谁在何时修改  
git blame src/auth.ts  

# 追溯指定行范围  
git blame -L 50,70 src/auth.ts  

# blame 时忽略空白字符变更  
git blame -w src/auth.ts  

# 查找某行代码被删除的时间(遍历完整历史)  
git log -S "function oldName" --oneline  

# 查找某正则表达式模式被添加或删除的时间  
git log -G "TODO.*hack" --oneline  

# 跟踪文件重命名历史  
git log --follow --oneline -- src/new-name.ts  

# 显示每行最后一次修改的提交(忽略文件移动)  
git blame -M src/auth.ts  

# 显示含文件变更统计的日志  
git log --stat --oneline -20  

# 显示影响特定文件的所有提交  
git log --oneline -- src/auth.ts  

# 显示某次提交的完整差异  
git show abc123  

标签与发布

# 创建带注释的标签(推荐用于正式发布)  
git tag -a v1.2.0 -m "Release 1.2.0: Added auth module"  

# 创建轻量级标签  
git tag v1.2.0  

# 为历史提交打标签  
git tag -a v1.1.0 abc123 -m "Retroactive tag for release 1.1.0"  

# 列出标签  
git tag -l  
git tag -l "v1.*"  

# 推送标签  
git push origin v1.2.0      # 推送单个标签  
git push origin --tags       # 推送所有标签  

# 删除标签  
git tag -d v1.2.0            # 删除本地标签  
git push origin --delete v1.2.0  # 删除远程标签  

提示与建议

  • git rebase -i 是最有价值的高级 Git 命令,应优先掌握。
  • 切勿对已推送到共享分支的提交执行变基。仅应在本地或功能分支上使用变基。
  • git reflog 是你的安全网。若意外丢失提交,它们几乎总能在 90 天内恢复。
  • 配合自动化测试脚本使用 git bisect run,比手动二分查找更快,且可避免人为失误。
  • 工作树(worktree)比多次克隆更节省资源 —— 它们共享同一份 .git 存储。
  • 除非有明确需求,否则优先选用 git subtree 而非 git submodule。子树对协作者更友好。
  • 全局启用 rerere。它能记住冲突解决方案,让你永远不必重复解决同一冲突。
  • 始终使用 git stash push -m "description" 而非裸用 git stash。当你拥有 5 个 stash 时,你会感激自己。
  • git log -S "string"(pickaxe 功能)是查找函数或变量被添加/删除时间的最快方式。

相关专题

更多
git怎么对比两个版本的文件内容
git怎么对比两个版本的文件内容

要对比两个版本的 git 文件,请使用 git diff 命令:git diff 比较工作树和暂存区之间的差异。git diff 比较两个提交或标签之间的差异。git diff 输出显示差异块,其中 + 表示添加的行,- 表示删除的行, 表示修改的行。可使用 gitkraken、meld、beyond compare 等可视化工具更直观地查看差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.09

2281

6

git提交错误怎么撤回
git提交错误怎么撤回

git提交错误撤回的方法:git reset head^:撤回最后一次提交,恢复到提交前状态。git revert head:创建新提交,内容与之前提交相反。git reset :使用提交的 sha-1 哈希撤回指定提交。交互式舞台区:标记要撤回的特定更改,然后提交,排除已撤回更改。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.09

2517

7

git撤销提交的commit
git撤销提交的commit

Git是一个强大的版本控制系统,它提供了很多功能帮助开发人员有效地管理和控制代码的变更,本专题为大家提供git 撤销提交的commit相关的各种文章内容,供大家免费下载体验。

2023.07.24

714

5

git和svn的区别
git和svn的区别

git和svn的区别:1、定义不同;2、模型类型不同;3、存储单元不同;4、是否拥有全局版本号;5、内容完整性不同;6、版本库不同;7、克隆目录速度不同;8、分支不同。php中文网为大家带来了git和svn的相关知识、以及相关文章等内容。

2023.07.06

1260

6

自建git服务器
自建git服务器

git服务器是目前流行的分布式版本控制系统之一,可以让多人协同开发同一个项目。本专题为大家提供自建git服务器相关的各种文章、以及下载和课程。

2023.07.05

3859

9

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

0

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

0

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

0

15

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

2026.10.22

0

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
vscode手册
vscode手册

共0课时 | 0人学习

Git 教程
Git 教程

共21课时 | 8.1万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.9万人学习