Git 進階技巧全攻略:Interactive Rebase、Bisect、Worktree 與鉤子自動化

前端工程(更新於 2026年5月18日)

你只用了 Git 20% 的能力

大多數開發者日常只用 addcommitpushpullmerge。Git 的真正威力在於:精確控制歷史、快速定位 Bug、並行多任務、自動化工作流程


一、Interactive Rebase:重塑提交歷史

基本操作

git rebase -i HEAD~5

開啟編輯器顯示最近 5 個提交:

pick a1b2c3f feat: 新增使用者列表頁面
pick d4e5f6g fix: 修復列表排序問題
pick h7i8j9k feat: 新增搜尋功能
pick l0m1n2o chore: 更新依賴
pick p3q4r5s feat: 新增分頁元件

六種操作

命令 作用 使用場景
pick 保留提交 預設
squash 合併到上一個提交 多個小修復合為一個
fixup 合併並捨棄訊息 同上,不保留訊息
reword 修改提交訊息 訊息有錯字
edit 暫停並修改提交 拆分或修改內容
drop 捨棄提交 移除錯誤提交

實戰:整理功能分支

# 原始提交
pick abc1234 feat: 使用者模組 WIP
pick def5678 fix: 修復空指標
pick ghi9012 fix: 修復型別錯誤
pick jkl3456 feat: 新增搜尋
pick mno7890 chore: 格式化程式碼

# 整理後
pick abc1234 feat: 新增使用者模組
fixup def5678   # 合併到 abc1234
fixup ghi9012   # 合併到 abc1234
pick jkl3456 feat: 新增搜尋功能
drop mno7890   # 捨棄格式化提交

自動 fixup

# 建立 fixup 提交(標記目標提交)
git commit --fixup=abc1234

# 自動變基,fixup 提交會找到目標並合併
git rebase -i --autosquash

二、Git Bisect:二分查找 Bug 引入點

當 Bug 出現但不知道哪個提交引入時,bisect 用二分查找快速定位。

手動 Bisect

# 開始二分查找
git bisect start

# 標記目前版本有 Bug
git bisect bad

# 標記已知的好版本
git bisect good v2.0.0

# Git 自動 checkout 中間版本
# 測試後標記
git bisect good   # 或 git bisect bad

# 重複直到找到引入 Bug 的提交
# Git 輸出:abc1234 is the first bad commit

# 結束查找
git bisect reset

自動化 Bisect

# 用腳本自動測試每個版本
git bisect start HEAD v2.0.0
git bisect run npm test

# 或自訂腳本
git bisect run ./scripts/test-bug.sh
#!/bin/bash
# scripts/test-bug.sh
npm run build
if curl -s http://localhost:3000/api/health | grep -q "ok"; then
  exit 0  # good
else
  exit 1  # bad
fi

效率:1000 個提交只需 10 次二分(log₂(1000) ≈ 10)。


三、Git Worktree:同時工作在多個分支

問題

正在 feature/A 上開發,突然需要緊急修復 hotfix/B——不想 stash,不想新建 clone。

解決

# 為 hotfix 建立工作樹
git worktree add ../hotfix-B hotfix/B

# 在 ../hotfix-B 目錄工作,不影響目前分支
cd ../hotfix-B
# 修復、提交、推送
git add . && git commit -m "fix: 緊急修復"
git push

# 回到原工作
cd ../main-project
# 繼續開發 feature/A,完全不受影響

# 清理工作樹
git worktree remove ../hotfix-B

管理工作樹

# 列出所有工作樹
git worktree list

# 鎖定工作樹(防止意外刪除)
git worktree lock ../hotfix-B

# 解鎖
git worktree unlock ../hotfix-B
對比 git stash git worktree git clone
磁碟佔用 0 僅差異檔案 全量
切換成本 stash + checkout cd 切目錄 cd 切目錄
並行工作 不支援 支援 支援
共享 .git

四、Git Hooks:自動化工作流程

客戶端鉤子

鉤子 觸發時機 用途
pre-commit git commit 程式碼檢查、格式化
prepare-commit-msg 編輯提交訊息前 自動新增前綴
commit-msg 提交訊息寫完後 校驗訊息格式
pre-push git push 執行測試
post-checkout 切換分支後 安裝依賴

服務端鉤子

鉤子 觸發時機 用途
pre-receive 接收推送前 權限校驗
update 每個引用更新前 分支保護
post-receive 接收推送後 觸發 CI/CD

使用 Husky + lint-staged

npm install husky lint-staged --save-dev
npx husky init
// .husky/pre-commit
npx lint-staged
// package.json
{
  "lint-staged": {
    "*.{js,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.css": [
      "stylelint --fix"
    ]
  }
}

commitlint 校驗提交訊息

npm install @commitlint/cli @commitlint/config-conventional --save-dev
// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'build', 'ci', 'chore', 'revert',
    ]],
    'subject-max-length': [2, 'always', 100],
  },
};
# .husky/commit-msg
npx --no -- commitlint --edit $1

五、Git Stash 進階用法

多個 Stash

# 帶訊息的 stash
git stash push -m "WIP: 使用者列表搜尋功能"

# 列出所有 stash
git stash list
# stash@{0}: On feature/search: WIP: 使用者列表搜尋功能
# stash@{1}: On feature/order: WIP: 訂單詳情頁

# 應用特定 stash
git stash apply stash@{1}

# 部分暫存
git stash push -m "只暫存 CSS" -- '**/*.css'

從 Stash 建立分支

git stash branch feature/search stash@{0}
# 建立新分支並應用 stash,適合 WIP 變成正式分支

六、Git Log 進階查詢

搜尋提交內容

# 搜尋包含特定字串的提交
git log -S "function calculateTotal"

# 搜尋匹配正則的提交
git log -G "calculate.*Total"

# 搜尋特定檔案的歷史
git log --follow -- src/utils/calc.ts

# 檢視每次提交的檔案變更統計
git log --stat

# 檢視每次提交的具體差異
git log -p -- src/utils/calc.ts

格式化輸出

# 自訂格式
git log --format="%h %ad | %s%d [%an]" --date=short

# 輸出:
# a1b2c3f 2026-05-30 | feat: 新增搜尋功能 (HEAD -> main) [張三]
# d4e5f6g 2026-05-29 | fix: 修復排序問題 [李四]

檢視分支合併圖

git log --graph --oneline --all --decorate

七、Git Reflog:時光機

reflog 記錄 HEAD 的每一次移動,即使提交被「刪除」也能找回。

# 檢視操作歷史
git reflog
# a1b2c3f HEAD@{0}: commit: feat: 新功能
# d4e5f6g HEAD@{1}: rebase: 繼續變基
# h7i8j9k HEAD@{2}: reset: moving to HEAD~1
# l0m1n2o HEAD@{3}: commit: 被誤刪的提交

# 恢復誤刪的提交
git cherry-pick l0m1n2o

# 或直接回到某個狀態
git reset --hard HEAD@{3}

保留期:預設 90 天(gc.reflogExpire),未引用的提交 30 天。


八、實用別名設定

git config --global alias.lg "log --graph --oneline --all --decorate"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.unstage "reset HEAD --"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.wip "commit -m 'WIP'"
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status

使用:git lggit lastgit unstage file.ts 等。

#Git#版本控制#开发效率