Git 大型檔案處理

GitHub 對單一檔案有 100 MB 的大小限制,超過就無法 push。這篇說明如何處理大型檔案的問題。

GitHub 檔案大小限制

當你 push 超過 100 MB 的檔案時,會看到錯誤訊息:

remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: File path/to/large-file is 111.98 MB; this exceeds GitHub's file size limit of 100.00 MB

從 Git 歷史中移除大型檔案

如果你已經不小心 commit 了大型檔案,需要從 Git 歷史中完全移除它。

方法一:使用 git filter-branch

# 1. 到 Git 專案根目錄
cd your-repository

# 2. 從 Git 歷史中移除檔案
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch path/to/large-file" \
  --prune-empty --tag-name-filter cat -- --all
這個指令會從 Git 歷史中永久移除該檔案,如果是重要的檔案,記得先備份!

方法二:使用 git filter-repo(推薦)

git filter-repo 是比較新的工具,效能更好:

# 安裝
pip install git-filter-repo

# 移除檔案
git filter-repo --path path/to/large-file --invert-paths

方法三:使用 BFG Repo-Cleaner

BFG 是專門用來清理 Git 歷史的工具:

# 下載 BFG
# 移除大於 100M 的檔案
java -jar bfg.jar --strip-blobs-bigger-than 100M your-repo.git

清理完成後

# 1. 加到 .gitignore 避免再次 commit
echo "path/to/large-file" >> .gitignore

# 2. 強制推送到遠端
git push origin --force --all

# 3. 清理本地
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Git LFS(Large File Storage)

如果你確實需要在 Git 追蹤大型檔案(如圖片、影片、資料集),可以使用 Git LFS。

安裝 Git LFS

# macOS
brew install git-lfs

# Ubuntu
sudo apt install git-lfs

# Windows(使用 Git for Windows 已包含)

設定 Git LFS

# 初始化(每個系統只需執行一次)
git lfs install

# 追蹤特定類型的檔案
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "data/*.csv"

# 確保 .gitattributes 被 commit
git add .gitattributes
git commit -m "Configure Git LFS"

使用 Git LFS

設定好之後,正常使用 Git 即可:

git add large-file.psd
git commit -m "Add design file"
git push

Git LFS 會自動把大型檔案存到 LFS 伺服器,Git repository 只儲存指標。

查看 LFS 追蹤的檔案

# 查看追蹤規則
git lfs track

# 查看 LFS 管理的檔案
git lfs ls-files

GitHub LFS 限制

GitHub 免費帳號的 LFS 限制:

  • 儲存空間:1 GB
  • 每月頻寬:1 GB

超過需要購買額外的 data pack。

預防大型檔案問題

設定 .gitignore

常見應該忽略的大型檔案:

# 壓縮檔
*.zip
*.tar.gz
*.rar

# 影片
*.mp4
*.mov
*.avi

# 資料檔
*.csv
*.sql
*.db

# 依賴套件
node_modules/
vendor/

# 編譯產出
dist/
build/

設定 pre-commit hook

在 commit 前檢查檔案大小:

#!/bin/sh
# .git/hooks/pre-commit

max_size=100000000  # 100MB in bytes

for file in $(git diff --cached --name-only); do
    if [ -f "$file" ]; then
        size=$(wc -c < "$file")
        if [ $size -gt $max_size ]; then
            echo "Error: $file is larger than 100MB"
            exit 1
        fi
    fi
done

其他平台的限制

平台單檔限制Repository 限制
GitHub100 MB建議 < 1 GB
GitLab無(但建議 < 1 GB)10 GB(免費)
Bitbucket2 GB(免費)

常見問題

已經 push 失敗,怎麼修復?

# 1. 移除大型檔案
git rm --cached large-file.zip

# 2. 修改最後一個 commit
git commit --amend --no-edit

# 3. 如果是更早的 commit,用 filter-branch 或 filter-repo

檔案已經在 .gitignore 但還是被追蹤

# 從 Git 移除(保留本地檔案)
git rm --cached large-file.zip
git commit -m "Remove large file from tracking"