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
本站提供瀏覽器本地工具,免註冊即可試用 →