Git 高级工作流与冲突解决实战
Git 工作流全景对比
选择合适的 Git 工作流是团队协作的基石。不同规模、不同发布节奏的团队需要不同的分支策略。
三大主流工作流
| 工作流 | 分支模型 | 适用场景 | 发布节奏 |
|---|---|---|---|
| Git Flow | main + develop + feature + release + hotfix | 有明确版本号的项目 | 计划发布(v1.0、v2.0) |
| GitHub Flow | main + feature | 持续部署的 Web/SaaS 项目 | 持续发布 |
| Trunk-Based | main + 短命 feature(<1天) | 高成熟度 CI/CD 团队 | 持续集成+Feature Flag |
Git Flow 详解
Git Flow 由 Vincent Driessen 提出,是最经典的分支模型:
# 初始化 Git Flow(需安装 git-flow)
git flow init
# 开始功能开发
git flow feature start user-auth
# → 从 develop 创建 feature/user-auth
# 完成功能(自动合并回 develop 并删除分支)
git flow feature finish user-auth
# 开始发布准备
git flow release start v1.2.0
# → 从 develop 创建 release/v1.2.0
# 完成发布(合并到 main + develop,打 tag)
git flow release finish v1.2.0
# 紧急修复
git flow hotfix start critical-bug
# → 从 main 创建 hotfix/critical-bug
git flow hotfix finish critical-bug
# → 合并到 main + develop,打 tag
分支生命周期图:
main: ●────────────────●────────●
\ / /
develop: ●──●──●──●──●──●──●──●──●──●
/ / \ /
feature: ●──●──● release: ●──● hotfix: ●──●
GitHub Flow 详解
极简模型,适合持续部署:
# 1. 从 main 创建功能分支
git checkout -b feature/add-search main
# 2. 开发并提交
git add . && git commit -m "feat: add search component"
# 3. 推送并创建 PR
git push -u origin feature/add-search
# 4. Code Review 通过后合并到 main
# 5. 自动部署到生产环境
Trunk-Based Development 详解
所有人在 main(trunk)上频繁集成,用 Feature Flag 控制未完成功能:
# 短命分支(<1 天必须合并)
git checkout -b fix/login-timeout main
git add . && git commit -m "fix: login timeout handling"
git push -u origin fix/login-timeout
# → CI 通过后立即合并,删除分支
# Feature Flag 示例(代码中控制)
# if (flags.NEW_SEARCH_ENABLED) {
# return newSearch(query);
# }
# return legacySearch(query);
工作流优缺点对比
| 维度 | Git Flow | GitHub Flow | Trunk-Based |
|---|---|---|---|
| 复杂度 | 高 | 低 | 中 |
| 并行开发 | 优秀 | 良好 | 优秀(需 Feature Flag) |
| 发布可控性 | 强 | 弱 | 中 |
| 冲突风险 | 高(长期分支) | 低 | 最低 |
| 回滚难度 | 容易(hotfix 分支) | 容易(revert PR) | 需要 Feature Flag |
| CI/CD 友好度 | 中 | 高 | 最高 |
| 适合团队规模 | 5-50 人 | 2-20 人 | 10+ 成熟团队 |
💡 使用 Hash 工具 生成提交签名,确保代码完整性。
Interactive Rebase 逐步实战
Interactive Rebase 是 Git 中最强大的历史改写工具,掌握它等于掌握了提交历史的"时光机"。
基本语法
# 交互式变基最近 3 个提交
git rebase -i HEAD~3
# 交互式变基到指定提交之后
git rebase -i abc1234^
# 编辑器中会显示:
# pick f1a2b3c feat: add user model
# pick d4e5f6g fix: validation error
# pick h7i8j9k docs: update README
Squash:合并提交
将多个小提交压缩为一个有意义的提交:
git rebase -i HEAD~3
# 修改为:
# pick f1a2b3c feat: add user model
# squash d4e5f6g fix: validation error
# squash h7i8j9k docs: update README
# → 3 个提交合并为 1 个,编辑合并后的提交信息
典型场景:把 "WIP"、"fix typo"、"fix again" 等零碎提交合并为一条有意义的记录。
Fixup:静默合并
与 squash 类似,但自动丢弃被合并提交的 message:
git rebase -i HEAD~3
# pick f1a2b3c feat: add user model
# fixup d4e5f6g fix: validation error
# fixup h7i8j9k fix: another fix
# → 只保留第一个提交的 message
更快捷的方式——提交时直接标记 fixup:
git commit --fixup=f1a2b3c
# 然后一键自动变基:
git rebase -i --autosquash HEAD~3
Reorder:调整提交顺序
直接在编辑器中调整行的顺序:
git rebase -i HEAD~3
# 原顺序:
# pick f1a2b3c feat: add user model
# pick d4e5f6g feat: add user service
# pick h7i8j9k test: user model test
# 调整为(测试紧跟模型):
# pick f1a2b3c feat: add user model
# pick h7i8j9k test: user model test
# pick d4e5f6g feat: add user service
Edit:拆分提交
将一个过大的提交拆分为多个:
git rebase -i HEAD~2
# pick f1a2b3c feat: add user module (too large)
# edit d4e5f6g feat: add auth module
# Git 暂停在 edit 标记的提交处
git reset HEAD~1
# 现在所有文件回到暂存区,可以分批提交
git add src/models/user.ts
git commit -m "feat: add user model"
git add src/services/user.ts
git commit -m "feat: add user service"
git rebase --continue
Rebase 中途操作
# 继续下一个提交
git rebase --continue
# 跳过当前提交
git rebase --skip
# 放弃整个 rebase,回到原始状态
git rebase --abort
⚠️ 黄金法则:永远不要 rebase 已经推送到远程共享分支的提交!这会导致其他人的历史混乱。
Merge vs Rebase 深度对比
这是 Git 社区最经典的争论,两者各有适用场景。
可视化对比
Merge——保留完整历史,产生合并提交:
main: ●──●──●──M──●
\ /
feature: ●──●
Rebase——线性历史,无合并提交:
main: ●──●──●──●'──●'
↑ feature 的提交重放到 main 之后
何时用 Merge
# 合并 feature 分支到 main(保留分支历史)
git checkout main
git merge --no-ff feature/user-auth
# --no-ff 禁止快进合并,确保产生合并提交
适用场景:
- 合并 feature 分支到 main/develop
- 需要保留分支存在的痕迹
- 团队要求完整的项目历史
何时用 Rebase
# 在 feature 分支上同步 main 的更新
git checkout feature/user-auth
git rebase main
# → feature 的提交"接在"main 最新提交之后
适用场景:
- 同步上游分支更新到本地 feature 分支
- 清理本地零碎提交
- 保持提交历史线性可读
对比总结
| 维度 | Merge | Rebase |
|---|---|---|
| 历史 | 保留真实分支历史 | 重写为线性历史 |
| 合并提交 | 有(可能很多) | 无 |
| 可读性 | 复杂分支图 | 干净线性 |
| 安全性 | 安全(不修改历史) | 危险(改写已推送的提交) |
| 冲突处理 | 一次性解决 | 逐提交解决 |
| 回滚 | git revert -m |
需要 rebase 或 reset |
| 推荐场景 | 合并到主分支 | 同步上游更新 |
实战建议
# 推荐的团队工作流组合策略:
# 1. feature 分支开发期间:用 rebase 同步 develop
git checkout feature/x
git fetch origin
git rebase origin/develop
# 2. feature 完成后:用 merge(--no-ff)合回 develop
git checkout develop
git merge --no-ff feature/x
# 3. develop 到 main:用 merge(--no-ff)
git checkout main
git merge --no-ff develop
冲突解决策略
冲突是协作开发的常态,掌握系统化的解决策略比"碰运气"高效得多。
三路合并(3-Way Merge)原理
Git 使用三路合并算法:
Base(共同祖先)
/ \
Ours Theirs
\ /
Merge Result
- 找到两个分支的共同祖先(Base)
- 对比 Ours vs Base、Theirs vs Base
- 只有一方修改 → 自动合并
- 双方修改同一行 → 冲突,需手动解决
# 查看冲突涉及的文件
git diff --name-only --diff-filter=U
# 查看冲突的详细内容
git diff
手动解决冲突
冲突标记格式:
<<<<<<< HEAD
当前分支的内容
=======
合并分支的内容
>>>>>>> feature/other-branch
解决步骤:
# 1. 打开冲突文件,手动编辑
# 2. 删除冲突标记,保留正确内容
# 3. 标记为已解决
git add <conflicted-file>
# 4. 完成合并
git commit
# 或 rebase 中:
git rebase --continue
使用合并工具
# 使用 VS Code 作为合并工具
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# 使用 vimdiff
git config --global merge.tool vimdiff
# 启动合并工具
git mergetool
git rerere:自动记忆冲突解决
rerere(Reuse Recorded Resolution)让 Git 记住你如何解决同类冲突,下次自动应用:
# 启用 rerere(全局)
git config --global rerere.enabled true
# 或仅在特定仓库启用
cd your-repo
git config rerere.enabled true
工作原理:
- 首次遇到冲突 → 手动解决 → Git 记录解决方案
- 再次遇到相同冲突 → 自动应用之前的解决方案
- 如果自动解决不理想 →
git rerere forget删除记忆
# 查看已记录的冲突解决方案
git rerere status
# 忘记当前冲突的记录解决方案
git rerere forget
# 手动触发重放
git rerere
典型场景:长期维护的 feature 分支反复与 develop 合并,同样的冲突反复出现。
冲突解决策略选择
| 策略 | 适用场景 | 命令 |
|---|---|---|
| 手动编辑 | 少量冲突、需要仔细判断 | 直接编辑文件 |
| 合并工具 | 大量冲突、需要可视化 | git mergetool |
| Ours 策略 | 完全采用我们的版本 | git merge -X ours |
| Theirs 策略 | 完全采用对方的版本 | git merge -X theirs |
| rerere | 重复出现的同类冲突 | git config rerere.enabled true |
💡 使用 JSON 格式化 工具整理 package.json 冲突后的内容。
Cherry-Pick 与其陷阱
Cherry-pick 允许你将某个提交"摘"到当前分支,而不合并整个分支。
基本用法
# 摘取单个提交
git cherry-pick abc1234
# 摘取多个提交
git cherry-pick abc1234 def5678
# 摘取一个范围(不包含 start,包含 end)
git cherry-pick start..end
# 摘取一个范围(包含 start 和 end)
git cherry-pick start^..end
常见陷阱
陷阱 1:重复提交
# feature 分支上的提交 abc1234 已通过 merge 合并到 main
# 后来又 cherry-pick 同一个提交
git cherry-pick abc1234
# → 产生一个新提交(不同 SHA),内容相同
# → Git 视为两个不同的提交,未来 merge 可能产生空合并或冲突
陷阱 2:遗漏依赖提交
# 提交 B 依赖提交 A 的修改
# 只 cherry-pick B 而不 pick A
git cherry-pick B
# → 可能编译失败或产生 bug
陷阱 3:冲突处理
# cherry-pick 遇到冲突
git cherry-pick abc1234
# CONFLICT!
# 解决冲突后继续
git add .
git cherry-pick --continue
# 或放弃本次 cherry-pick
git cherry-pick --abort
安全使用 Cherry-Pick 的原则
- 只 cherry-pick 到不打算 merge 的分支(如 hotfix 到 release)
- 确保摘取的提交是自包含的(不依赖其他未摘取的提交)
- 记录已 cherry-pick 的提交,避免重复
- 优先考虑 merge 或 rebase,cherry-pick 是最后手段
典型场景:Hotfix 同步
# 在 main 上紧急修复
git checkout main
git cherry-pick hotfix-commit-sha
# 同步到 develop
git checkout develop
git cherry-pick hotfix-commit-sha
# 同步到其他 release 分支
git checkout release/v1.1
git cherry-pick hotfix-commit-sha
Bisect:二分法定位 Bug
git bisect 用二分查找法在提交历史中定位引入 bug 的提交,比逐个排查高效数倍。
基本流程
# 1. 开始二分查找
git bisect start
# 2. 标记当前版本为"坏"
git bisect bad
# 3. 标记某个已知的好版本
git bisect good v1.0.0
# Git 自动 checkout 到中间提交
# 测试该版本...
# 4. 标记中间提交
git bisect good # 如果这个版本没问题
git bisect bad # 如果这个版本有问题
# 5. 重复步骤 4,直到 Git 找到第一个坏提交
# → Git 显示:abc1234 is the first bad commit
# 6. 结束二分查找
git bisect reset
自动化 Bisect
用脚本自动判断每个提交的好坏:
# 用测试脚本自动判断
git bisect start HEAD v1.0.0 --
git bisect run npm test
# 用自定义脚本
git bisect run ./scripts/bisect-test.sh
bisect-test.sh 示例:
#!/bin/bash
npm build || exit 125 # 跳过无法构建的提交
npm test
# exit 0 = good, exit 1 = bad, exit 125 = skip
Bisect 效率
对于 1000 个提交的范围,bisect 最多只需 10 次(log₂(1000) ≈ 10)即可定位到问题提交,而线性排查最差需要 1000 次。
Worktree:并行工作不切分支
git worktree 允许你在同一个仓库中同时检出多个分支到不同目录,无需 stash 或 clone。
基本用法
# 添加一个 worktree
git worktree add ../feature-x feature/x
# → 在 ../feature-x 目录检出 feature/x 分支
# 添加一个新分支的 worktree
git worktree add -b feature/y ../feature-y main
# → 创建 feature/y 分支并在 ../feature-y 检出
# 列出所有 worktree
git worktree list
# 移除 worktree
git worktree remove ../feature-x
# 强制移除(有未提交修改时)
git worktree remove --force ../feature-x
典型场景
# 场景1:同时在两个 feature 上工作
git worktree add ../feature-a feature/a
git worktree add ../feature-b feature/b
# → 两个目录互不干扰,可以同时用不同 IDE 打开
# 场景2:紧急修复不打断当前工作
git worktree add -b hotfix/urgent ../hotfix main
cd ../hotfix
# → 修复、提交、推送
cd ../main-project
git worktree remove ../hotfix
# 场景3:长时间运行测试
git worktree add ../test-branch test-env
# → 在 test-branch 跑测试,主目录继续开发
Worktree 注意事项
- 同一分支不能同时在两个 worktree 中检出
- 删除 worktree 前确保已提交或保存修改
- worktree 共享同一个
.git目录,节省磁盘空间
Stash 高级用法
git stash 临时保存未提交的修改,是"暂停当前工作"的最佳方式。
基本操作
# 保存所有修改(已跟踪文件的修改和暂存)
git stash
# 保存时添加描述
git stash push -m "WIP: user auth refactor"
# 查看所有 stash
git stash list
# 恢复最新的 stash
git stash pop
# 恢复但不删除 stash
git stash apply
# 恢复指定 stash
git stash apply stash@{2}
高级技巧
# 只 stash 某些文件
git stash push -m "partial" src/auth.ts src/auth.test.ts
# stash 未跟踪的文件(新文件)
git stash -u
# stash 所有文件(包括忽略的文件)
git stash -a
# stash 仅暂存区的内容
git stash --staged
# 查看某个 stash 的内容
git stash show -p stash@{0}
# 从 stash 创建分支
git stash branch feature/from-stash stash@{0}
Stash 多项管理
# 场景:多个 stash 堆积
git stash list
# stash@{0}: On feature/x: WIP: refactor
# stash@{1}: On feature/x: WIP: fix tests
# stash@{2}: On main: hotfix draft
# 删除指定 stash
git stash drop stash@{1}
# 清空所有 stash
git stash clear
Stash 与冲突
# pop/apply 遇到冲突时
git stash pop
# CONFLICT!
# 解决冲突后,手动删除 stash
git stash drop
# 或者放弃 pop
git checkout -- .
git stash pop # 重试
Git Hooks 自动化
Git Hooks 是在特定 Git 事件触发时自动执行的脚本,是本地自动化的利器。
常用 Hooks 位置
# Hooks 存储在 .git/hooks/ 目录
ls .git/hooks/
# applypatch-msg.sample
# pre-commit.sample
# commit-msg.sample
# ...
pre-commit:提交前检查
# 创建 pre-commit hook
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# 检查是否有 console.log
if git diff --cached | grep -q "console.log"; then
echo "❌ 发现 console.log,请移除后再提交"
exit 1
fi
# 运行 lint
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint 检查失败"
exit 1
fi
# 运行类型检查
npm run typecheck
if [ $? -ne 0 ]; then
echo "❌ 类型检查失败"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/pre-commit
commit-msg:规范提交信息
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash
COMMIT_MSG=$(cat "$1")
# 校验 Conventional Commits 格式
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,100}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "❌ 提交信息不符合 Conventional Commits 规范"
echo "格式: type(scope): description"
echo "示例: feat(auth): add login page"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/commit-msg
推荐:使用 Husky + lint-staged
手动管理 hooks 不便于团队共享,推荐使用工具:
# 安装 Husky
npm install husky -D
npx husky init
# 添加 pre-commit hook
echo "npx lint-staged" > .husky/pre-commit
# 配置 lint-staged(package.json)
# "lint-staged": {
# "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
# "*.{json,md}": ["prettier --write"]
# }
# 添加 commit-msg hook
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
其他实用 Hooks
| Hook | 触发时机 | 典型用途 |
|---|---|---|
| pre-push | git push 前 |
运行完整测试套件 |
| post-merge | git pull 合并后 |
自动 npm install |
| post-checkout | 切换分支后 | 切换 node_modules |
| prepare-commit-msg | 编辑提交信息前 | 自动添加 issue 编号 |
Git LFS:大文件存储
Git 对二进制大文件(图片、视频、模型等)处理效率低,Git LFS 解决此问题。
安装与初始化
# 安装 Git LFS
git lfs install
# 跟踪大文件类型
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.model"
git lfs track "datasets/**"
# 查看跟踪规则
git lfs track
# 提交 .gitattributes(跟踪规则需纳入版本控制)
git add .gitattributes
git commit -m "chore: configure Git LFS"
日常使用
# 正常 add/commit,LFS 自动处理
git add large-file.psd
git commit -m "feat: add design file"
# 查看已用 LFS 存储的文件
git lfs ls-files
# 查看 LFS 占用空间
git lfs ls-files --size
# 拉取 LFS 对象
git lfs pull
# 仅拉取指定文件的 LFS 对象
git lfs fetch --include="*.psd"
LFS 迁移已有文件
# 将已跟踪的 .psd 文件迁移到 LFS
git lfs migrate import --include="*.psd"
# 迁移所有历史中的大文件(重写历史!)
git lfs migrate import --include="*.psd" --everything
LFS 注意事项
- 需要服务器支持(GitHub/GitLab 均支持,有配额限制)
.gitattributes必须提交到仓库- clone 时默认不下载 LFS 对象(需
git lfs pull) - LFS 有存储和带宽配额,注意成本
Monorepo 策略
Monorepo 将多个项目放在同一仓库中,便于共享代码和统一管理。
目录结构
monorepo/
├── apps/
│ ├── web/ # 前端应用
│ ├── mobile/ # 移动端应用
│ └── api/ # 后端服务
├── packages/
│ ├── ui/ # 共享 UI 组件
│ ├── utils/ # 共享工具函数
│ └── config/ # 共享配置
├── package.json
├── turbo.json # Turborepo 配置
└── pnpm-workspace.yaml
稀疏检出(Sparse Checkout)
只检出需要的目录,加速 clone:
# 启用稀疏检出
git sparse-checkout init --cone
# 只检出 apps/web 和 packages/ui
git sparse-checkout set apps/web packages/ui
# 添加更多目录
git sparse-checkout add apps/api
# 查看当前检出的目录
git sparse-checkout list
浅克隆(Shallow Clone)
只获取最近的提交历史:
# 只获取最近 1 个提交
git clone --depth=1 https://github.com/org/monorepo.git
# 获取最近 10 个提交
git clone --depth=10 https://github.com/org/monorepo.git
# 后续获取更多历史
git fetch --unshallow
Monorepo 工具选择
| 工具 | 语言 | 核心特性 |
|---|---|---|
| Turborepo | JS/TS | 增量构建、远程缓存、Pipeline |
| Nx | JS/TS | 依赖图分析、受影响项目检测 |
| Lerna | JS/TS | 版本管理、发布流程 |
| Bazel | 多语言 | Google 级别的增量构建 |
| PNPM Workspace | JS/TS | 原生 monorepo 支持 |
常见错误与救援
Detached HEAD
# 误入 detached HEAD 状态
git checkout abc1234
# → HEAD detached at abc1234
# 查看当前状态
git status
# → HEAD detached at abc1234
# 救援方案1:创建新分支保存
git checkout -b feature/from-detached
# 救援方案2:如果已有未提交修改
git stash
git checkout main
git stash pop
Force Push 恢复
# 有人 force push 覆盖了远程分支
# 1. 用 reflog 找到被覆盖的提交
git reflog
# abc1234 HEAD@{0}: checkout: moving from main to feature/x
# def5678 HEAD@{1}: commit: feat: important feature
# 2. 恢复到指定提交
git checkout def5678
git checkout -b feature/x-recovered
git push -f origin feature/x-recovered:feature/x
Reflog:终极救援工具
Reflog 记录了 HEAD 的每一次移动,即使提交被"删除"也能找回:
# 查看完整 reflog
git reflog
# 查看指定分支的 reflog
git reflog show feature/x
# 查看最近 10 条
git reflog -10
# 恢复到 reflog 中的某个状态
git reset --hard HEAD@{5}
# 恢复被 reset 丢失的提交
git reflog
# 找到 reset 之前的提交 SHA
git cherry-pick <lost-commit-sha>
Reflog 的保留时间:
[gc]
reflogExpire = 90.days
reflogExpireUnreachable = 30.days
误提交大文件
# 1. 从历史中彻底删除大文件
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch path/to/large-file.mp4' \
--prune-empty -- --all
# 2. 或使用更快的 git-filter-repo
pip install git-filter-repo
git filter-repo --path path/to/large-file.mp4 --invert-paths
# 3. 强制推送更新远程
git push --force --all
# 4. 清理本地
git reflog expire --expire=now --all
git gc --prune=now --aggressive
.gitignore 最佳实践
分层策略
# 全局忽略(~/.gitignore_global)
# 操作系统文件
.DS_Store
Thumbs.db
Desktop.ini
# IDE
.idea/
.vscode/
*.swp
# 环境变量
.env
.env.local
项目级 .gitignore
# 依赖
node_modules/
vendor/
.venv/
# 构建产物
dist/
build/
*.egg-info/
# 日志
*.log
logs/
# 测试覆盖率
coverage/
.nyc_output/
# 临时文件
*.tmp
*.temp
.cache/
# 大文件(配合 LFS)
# *.psd → 改用 LFS 跟踪而非忽略
忽略规则语法
# 忽略所有 .log 文件
*.log
# 但保留 important.log
!important.log
# 忽略 build 目录下所有内容
build/**
# 忽略根目录的 TODO,不忽略子目录的
/TODO
# 忽略 doc 目录下的所有 .pdf
doc/**/*.pdf
# 忽略所有目录中的 __pycache__
__pycache__/
常见错误
# ❌ 错误:忽略已跟踪的文件不会生效
# 如果文件已经被 git 跟踪,加入 .gitignore 无效
# ✅ 正确做法:先取消跟踪
git rm --cached debug.log
# 然后加入 .gitignore
echo "debug.log" >> .gitignore
git add .gitignore
git commit -m "chore: ignore debug.log"
推荐模板
使用 gitignore.io 生成项目模板:
# 生成 Node + VSCode + macOS 的忽略规则
curl -sL https://www.gitignore.io/api/node,visualstudiocode,macos > .gitignore
💡 使用 Base64 编码 工具对 .env 文件中的敏感信息进行编码传输。
FAQ
Q1:Rebase 过程中冲突太多怎么办?
如果 rebase 冲突过多,可以:
git rebase --abort放弃,改用git merge- 频繁从上游 rebase,减少累积差异
- 将大 feature 拆分为小 feature,减少单次 rebase 范围
Q2:如何撤销已推送的提交?
# 方案1:revert(安全,产生新提交)
git revert abc1234
git push
# 方案2:reset + force push(危险,改写历史)
git reset --hard abc1234^
git push --force
# ⚠️ 仅在确认无他人基于此提交工作时使用
Q3:如何查看某个文件的修改历史?
# 查看文件修改历史
git log --follow -p src/auth/login.ts
# 查看谁修改了文件的每一行
git blame src/auth/login.ts
# 查看文件在某个提交时的内容
git show abc1234:src/auth/login.ts
Q4:如何比较两个分支的差异?
# 查看分支间文件差异
git diff main..feature/x
# 查看分支间提交差异
git log main..feature/x --oneline
# 查看分支间统计
git diff main..feature/x --stat
Q5:如何清理本地已删除的远程分支?
# 修剪远程已删除的分支引用
git remote prune origin
# 或在 fetch 时自动修剪
git fetch -p
# 或配置自动修剪
git config --global fetch.prune true
Q6:如何处理 merge commit 的 revert?
# revert 合并提交需要指定保留哪个父分支
# -m 1:保留第一个父分支(通常是 main)
git revert -m 1 <merge-commit-sha>
Q7:如何让 Git 忽略文件权限变化?
git config core.fileMode false
Q8:如何加速大型仓库的 clone?
# 组合策略:浅克隆 + 稀疏检出 + 单分支
git clone --depth=1 --single-branch --filter=blob:none \
https://github.com/org/large-repo.git
本站提供浏览器本地工具,免注册即可试用 →