Git 進階工作流與衝突解決實戰

DevOps

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
  1. 找到兩個分支的共同祖先(Base)
  2. 對比 Ours vs Base、Theirs vs Base
  3. 只有一方修改 → 自動合併
  4. 雙方修改同一行 → 衝突,需手動解決
# 檢視衝突涉及的檔案
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

工作原理

  1. 首次遇到衝突 → 手動解決 → Git 記錄解決方案
  2. 再次遇到相同衝突 → 自動套用之前的解決方案
  3. 如果自動解決不理想 → 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 的原則

  1. 只 cherry-pick 到不打算 merge 的分支(如 hotfix 到 release)
  2. 確保摘取的提交是自包含的(不依賴其他未摘取的提交)
  3. 記錄已 cherry-pick 的提交,避免重複
  4. 優先考慮 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 衝突過多,可以:

  1. git rebase --abort 放棄,改用 git merge
  2. 頻繁從上游 rebase,減少累積差異
  3. 將大 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

本站提供瀏覽器本地工具,免註冊即可試用 →

#Git#工作流#冲突解决#Rebase#教程