name: git-advanced description: 高级Git工作流,包括工作树、二分查找、交互式变基、钩子和恢复技术
Git高级
工作树
# 为功能分支创建工作树(避免储藏)
git worktree add ../feature-auth feature/auth
# 创建带有新分支的工作树
git worktree add ../hotfix-123 -b hotfix/123 origin/main
# 列出所有工作树
git worktree list
# 合并后移除工作树
git worktree remove ../feature-auth
工作树允许您同时在多个分支上工作,无需储藏或提交进行中的工作。每个工作树都有自己的工作目录,但共享相同的 .git 仓库。
二分查找
# 开始二分查找,标记当前为坏提交和已知好提交
git bisect start
git bisect bad HEAD
git bisect good v1.5.0
# Git检出中点提交。测试后标记:
git bisect good # 如果这个提交工作正常
git bisect bad # 如果这个提交损坏
# 使用测试脚本自动化
git bisect start HEAD v1.5.0
git bisect run npm test
# 完成后重置
git bisect reset
二分查找通过提交进行二进制搜索,以找出哪个提交引入了错误。使用 run 的自动化二分查找是最快的方法。
交互式变基
# 交互式变基最近5个提交
git rebase -i HEAD~5
# 编辑器中的常见操作:
# pick - 保留提交不变
# reword - 更改提交消息
# edit - 停止以修改提交
# squash - 合并到前一个提交,保留两个消息
# fixup - 合并到前一个提交,丢弃此消息
# drop - 完全移除提交
# 将功能分支变基到最新的主分支
git fetch origin
git rebase origin/main
# 解决冲突后继续
git rebase --continue
# 如果出错则中止
git rebase --abort
Git钩子
#!/bin/sh
# .git/hooks/pre-commit
# 仅对暂存文件运行代码检查
STAGED_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(ts|tsx|js|jsx)$')
if [ -n "$STAGED_FILES" ]; then
npx eslint $STAGED_FILES --fix
git add $STAGED_FILES
fi
#!/bin/sh
# .git/hooks/commit-msg
# 强制使用常规提交格式
COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,72}$"
if ! echo "$COMMIT_MSG" | head -1 | grep -qE "$PATTERN"; then
echo "错误:提交消息必须遵循常规提交格式"
echo "示例:feat(auth): 添加OAuth2登录流程"
exit 1
fi
#!/bin/sh
# .git/hooks/pre-push
# 推送前运行测试
npm test
if [ $? -ne 0 ]; then
echo "测试失败。推送中止。"
exit 1
fi
恢复技术
# 撤销最后一次提交,但保留更改暂存
git reset --soft HEAD~1
# 使用reflog恢复已删除的分支
git reflog
git checkout -b recovered-branch HEAD@{3}
# 从特定提交恢复文件
git checkout abc1234 -- path/to/file.ts
# 查找丢失的提交(在重置或变基后悬空)
git fsck --lost-found
git show <dangling-commit-sha>
# 撤销变基
git reflog
git reset --hard HEAD@{5} # 指向变基开始前
有用别名
# ~/.gitconfig
[alias]
lg = log --graph --oneline --decorate --all
st = status -sb
co = checkout
unstage = reset HEAD --
last = log -1 HEAD --stat
branches = branch -a --sort=-committerdate
stash-all = stash push --include-untracked
conflicts = diff --name-only --diff-filter=U
反模式
- 不使用
--force-with-lease强制推送到共享分支 - 变基已经推送并共享的提交
- 不使用Git LFS提交大型二进制文件
- 不使用
git diff --staged审查就使用git add . - 不为构建产物、依赖项和密钥使用
.gitignore - 保持长期功能分支而不是频繁合并
检查清单
- [ ] 使用工作树进行并行分支工作,而非储藏
- [ ]
git bisect run使用测试命令自动化错误查找 - [ ] 交互式变基在合并到主分支前清理提交
- [ ] 预提交钩子在暂存文件上运行代码检查
- [ ] 通过提交消息钩子强制执行提交消息格式
- [ ] 使用
--force-with-lease而非--force进行强制推送 - [ ] 在任何破坏性操作前查阅reflog
- [ ]
.gitignore覆盖构建输出、依赖项和环境文件