Git Filter Repo 使用指南 - 更安全有效率的 Git 歷史重寫工具
在 Git 的世界中,有時候我們需要修改版本歷史,例如移除大型檔案、修改作者資訊或者重新整理提交訊息。雖然 Git 內建的 filter-branch 指令可以完成這些工作,但它速度慢且容易出錯。這就是為什麼我們需要認識 git-filter-repo 這個強大的工具。
什麼是 git-filter-repo?
git-filter-repo 是一個用 Python 撰寫的開源工具,專門用於重寫 Git 版本歷史。它是 git filter-branch 的替代品,提供了更好的效能、更簡單的使用方式和更安全的操作。
主要特點
- 執行速度比 filter-branch 快上約 50 倍
- 使用更直覺的命令介面
- 內建多種常用的重寫功能
- 提供完整的程式化 API
- 自動進行安全性檢查
安裝方式
你可以透過 pip 安裝:
1 | pip install git-filter-repo |
或是在 Ubuntu/Debian 系統使用:
1 | sudo apt install git-filter-repo |
常見使用情境
1. 移除意外推送的敏感資料
如果不小心將密碼、API 金鑰或其他敏感資訊推送到 Git 倉庫,需要立即處理:
1 | # 移除包含敏感資料的檔案 |
處理敏感資料外洩時的注意事項:
- 立即撤銷並更換所有外洩的密碼、金鑰等資訊
- 通知相關人員或組織關於資料外洩事件
- 檢查其他分支是否也包含敏感資料
- 考慮使用 git-secrets 或類似工具來預防未來的意外推送
預防措施:
- 使用
.gitignore排除敏感檔案 - 導入 pre-commit hooks 檢查敏感資料
- 將敏感資訊移至環境變數
- 使用加密的密碼管理工具
2. 移除大型檔案
當你不小心提交了大型檔案到 Git 倉庫,可以使用以下指令移除:
1 | git filter-repo --path-glob '*.zip' --invert-paths |
這個指令會移除所有 .zip 檔案的歷史記錄。
3. 修改作者資訊
如果需要修正作者的 email:
1 | git filter-repo --email-callback 'return email.replace("old@email.com", "new@email.com")' |
4. 將子目錄提升為根目錄
想要將專案中的某個子目錄變成新的根目錄:
1 | git filter-repo --subdirectory-filter folder_name |
使用注意事項
永遠在複製的倉庫中操作
在使用 git-filter-repo 之前,請先複製一份原始倉庫,避免不小心損壞原始資料。重寫是永久的
使用 git-filter-repo 後的修改無法復原,請確保你真的需要這麼做。需要強制推送
修改歷史後,需要使用git push --force來更新遠端倉庫。這可能會影響其他開發者,請事先與團隊溝通。移除快取
在執行前,建議先清除 Git 的快取:1
git gc --aggressive
與 git filter-branch 的比較
| 特性 | git-filter-repo | git filter-branch |
|---|---|---|
| 執行速度 | 非常快 | 較慢 |
| 使用難度 | 簡單 | 複雜 |
| 功能完整性 | 高 | 中 |
| 安全性檢查 | 有 | 無 |
| 維護狀態 | 活躍 | 已不建議使用 |
進階使用技巧
自訂重寫規則
git-filter-repo 支援使用 Python 腳本來定義複雜的重寫規則:
1 | from git_filter_repo import Blob, Reset |
批次修改提交訊息
1 | git filter-repo --message-callback 'return message.replace("[WIP]", "[DONE]")' |
結論
git-filter-repo 是一個強大且高效的 Git 歷史重寫工具。它不只解決了 git filter-branch 的效能問題,還提供了更多實用的功能。只要注意使用時的安全事項,它就是一個非常好用的工具。
