Git 重置提交記錄 恢復歷史 清理提交記錄
有時候,我們提交了一些隱私的數據例如密碼等到 Github 倉庫,就算更新了倉庫文件,但依舊會在 commit 歷史記錄中保存這部分數據。這個時候,我們就需要一種方法,可以把Github分支下所有提交記錄進行刪除!
本文將介紹幾種徹底重置 Git 提交記錄的方法,幫助你清理敏感信息或重新開始一個乾淨的歷史。
為什麼需要重置提交記錄?
常見場景
提交了敏感信息
- 密碼、API 密鑰
- 私鑰、證書文件
- 個人身份信息
提交了大文件
- 視頻、圖片資源
- 數據庫備份
- node_modules 目錄
歷史過於混亂
- 大量 WIP 提交
- 實驗性代碼
- 錯誤的提交信息
項目重構
- 完全重寫代碼
- 改變項目結構
- 遷移技術棧
方法一:使用 Orphan 分支(推薦)
這是最徹底的清理方式,創建一個完全沒有歷史的新分支。
操作步驟
一般使用新建分支,都會在當前 master 分支的基礎上克隆一份,如下圖所示:

# 1. 創建一個孤兒分支(沒有任何歷史)
git checkout --orphan latest_branch
# 2. 添加你想提交的所有文件到這個新分支
git add -A
git commit -m "commit message"
# 3. 先將舊分支刪除
git branch -D main
# 4. 再將新分支的名字改為舊分支的名字
git branch -m main
# 5. 最後提交所有本地操作到Github倉庫
git push -f origin main詳細解釋
步驟 1:創建孤兒分支
git checkout --orphan latest_branch發生了什麼:
- 創建了一個全新的分支
- 沒有任何提交歷史
- HEAD 指向這個新分支
- 工作區的文件保持不變
驗證:
git log
# 輸出:fatal: your current branch 'latest_branch' does not have any commits yet步驟 2:添加並提交文件
# 添加所有文件
git add -A
# 或者選擇性添加
git add src/
git add package.json
git add README.md
# 提交
git commit -m "feat: Initial clean commit"提示:
- 這是重新審視
.gitignore的好機會 - 確保不要再次提交敏感文件
- 可以整理項目結構
步驟 3:刪除舊分支
# 刪除本地的舊分支
git branch -D main注意:
-D是強制刪除,即使有未合併的更改- 如果分支名不是
main,替換為實際名稱(如master、develop)
步驟 4:重命名分支
# 將孤兒分支重命名為原來的名字
git branch -m main現在你有:
- 一個名為
main的分支 - 只有一個提交
- 沒有任何歷史包袱
步驟 5:強制推送到遠程
# 強制推送(覆蓋遠程分支)
git push -f origin main⚠️ 重要警告:
- 這會刪除遠程的所有歷史
- 所有協作者需要重新克隆倉庫
- 確保已通知團隊成員
完整示例
# 假設當前在 main 分支,有很多提交歷史
# 1. 創建孤兒分支
$ git checkout --orphan clean-slate
Switched to a new branch 'clean-slate'
# 2. 查看狀態(所有文件都顯示為未跟蹤)
$ git status
On branch clean-slate
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
src/
package.json
# 3. 更新 .gitignore
$ cat > .gitignore << EOF
node_modules/
.env
*.log
dist/
EOF
# 4. 添加文件
$ git add .
# 5. 提交
$ git commit -m "feat: Fresh start with clean history"
# 6. 刪除舊分支
$ git branch -D main
Deleted branch main (was abc1234).
# 7. 重命名
$ git branch -m main
# 8. 推送到遠程
$ git push -f origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 1.23 KiB | 1.23 MiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To github.com:user/repo.git
+ abc1234...def5678 main -> main (forced update)方法二:使用 Filter-Repo 清理歷史
如果你只想刪除特定的文件或目錄,而不是整個歷史,可以使用 git filter-repo。
安裝
# 使用 pip
pip install git-filter-repo
# 或使用 Homebrew
brew install git-filter-repo刪除特定文件
# 從歷史中刪除敏感文件
git filter-repo --path password.txt --path secret.key --invert-paths --force
# 刪除整個目錄
git filter-repo --path node_modules/ --invert-paths --force
# 刪除特定類型的所有文件
git filter-repo --path-glob '*.log' --invert-paths --force替換敏感內容
# 創建替換規則文件
cat > replacements.txt << EOF
password123==>REDACTED
api_key_abc123==>REDACTED
secret_token==>REDACTED
EOF
# 執行替換
git filter-repo --replace-text replacements.txt --force推送到遠程
# 強制推送
git push --force --all
git push --force --tags方法三:使用 BFG Repo-Cleaner
BFG 是一個更快、更簡單的替代方案。
安裝
# macOS
brew install bfg
# Linux
sudo apt install bfg
# 或下載 JAR 文件
wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar使用方法
# 刪除大文件(大於 100M)
bfg --strip-blobs-bigger-than 100M my-repo.git
# 刪除特定文件
bfg --delete-files password.txt my-repo.git
# 刪除包含敏感內容的文件
bfg --replace-text passwords.txt my-repo.git
# 清理
cd my-repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive方法四:重置到特定提交
如果你想保留部分歷史,可以重置到某個乾淨的提交。
# 1. 找到要保留的提交
git log --oneline
# 2. 硬重置到該提交
git reset --hard abc1234
# 3. 強制推送
git push -f origin main團隊協作時的注意事項
通知流程
# 1. 提前通知
echo "⚠️ 警告:我將重置 main 分支的歷史記錄
原因:移除了敏感信息
時間:今天下午 3 點
影響:所有人需要重新克隆倉庫"
# 2. 執行重置
# ... 執行上述任一方法 ...
# 3. 通知團隊重新克隆
echo "✅ 重置完成
請執行:
1. 備份你的本地更改
2. 刪除舊倉庫:rm -rf repo
3. 重新克隆:git clone <url>
4. 恢復你的更改"團隊成員的操作
# 方法 1:重新克隆(推薦)
cd ..
rm -rf repo
git clone https://github.com/user/repo.git
# 方法 2:重置本地分支
git fetch origin
git reset --hard origin/main
git clean -fd
# 方法 3:如果有本地提交
git fetch origin
git rebase origin/main
# 解決可能的衝突預防勝於治療
1. 完善 .gitignore
# 環境變量
.env
.env.local
.env.production
# 密鑰文件
*.pem
*.key
*.p12
id_rsa
id_ed25519
# 配置文件
config/secrets.yml
credentials.json
# 日誌文件
*.log
logs/
# 依賴
node_modules/
vendor/
# 構建產物
dist/
build/2. 使用預提交鉤子
創建 .git/hooks/pre-commit:
#!/bin/bash
# 檢查是否提交了敏感文件
if git diff --cached --name-only | grep -E '\.env|\.pem|\.key'; then
echo "❌ 錯誤:檢測到敏感文件!"
exit 1
fi
# 檢查是否包含密碼模式
if git diff --cached | grep -iE 'password\s*=\s*["\'][^"\']+["\']'; then
echo "❌ 錯誤:檢測到硬編碼密碼!"
exit 1
fi3. 使用 Git Secrets
# 安裝
brew install git-secrets
# 初始化
git secrets --install
# 添加規則
git secrets --add 'password\s*=\s*.+'
git secrets --add 'api_key\s*=\s*.+'
# 掃描歷史
git secrets --scan-history4. 環境變量管理
# ✅ 正確:使用環境變量
const apiKey = process.env.API_KEY;
# ❌ 錯誤:硬編碼
const apiKey = "sk-1234567890";創建 .env.example:
# 複製此文件為 .env 並填入真實值
API_KEY=your_api_key_here
DATABASE_URL=your_database_url
SECRET_KEY=your_secret_key常見問題排查
問題 1:推送被拒絕
# 錯誤:protected branch update failed
# 解決方案:
# 1. 臨時禁用分支保護
# 2. 執行推送
git push -f origin main
# 3. 重新啟用保護問題 2:GitHub 仍然顯示舊文件
# GitHub 會緩存內容,需要:
# 1. 等待幾分鐘
# 2. 硬刷新瀏覽器(Ctrl+Shift+R)
# 3. 如果還不行,聯繫 GitHub 支持問題 3:Fork 的倉庫怎麼辦?
# Fork 的倉庫不會自動更新
# 需要通知所有 Fork 所有者:
# 1. 刪除他們的 Fork
# 2. 重新 Fork 你的倉庫問題 4:CI/CD 失敗
# 重置後 CI/CD 可能需要:
# 1. 清除緩存
# 2. 重新配置環境變量
# 3. 更新部署腳本最佳實踐總結
選擇合適的方法
| 場景 | 推薦方法 | 難度 | 風險 |
|---|---|---|---|
| 完全重新開始 | Orphan 分支 | ⭐⭐ | 高 |
| 刪除特定文件 | filter-repo | ⭐⭐⭐ | 中 |
| 刪除大文件 | BFG | ⭐⭐ | 中 |
| 回退到某版本 | reset --hard | ⭐ | 中 |
操作清單
在執行重置前:
操作後檢查
總結
重置 Git 提交記錄是解決敏感信息洩露和歷史混亂的有效方法:
- Orphan 分支:最徹底,適合完全重新開始
- Filter-Repo:精確控制,適合刪除特定內容
- BFG:快速簡單,適合大文件清理
- Reset:部分保留,適合回退到穩定版本
記住:
- ⚠️ 這些操作都會改寫歷史
- 📢 務必提前通知團隊
- 💾 操作前務必備份
- 🔒 事後加強預防措施
下一步學習:
謹慎操作,安全第一!🔐