Hướng dẫn sử dụng git-sizer: “Cứu” repo Git phình to và chậm chạp

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Tại sao repo Git của bạn lại nặng như “đeo chì”?

Bạn đã bao giờ rơi vào cảnh git clone một dự án nhỏ mà mất tới 15 phút, hay mỗi lần git fetch lại đủ thời gian để đi pha một tách cafe? Mình từng xử lý một repo mà thư mục .git phình lên tới 8GB. Trong khi đó, source code thực tế chỉ nặng vỏn vẹn 120MB.

Sự thật là, lỗi hiếm khi nằm ở đống code bạn viết. Thủ phạm thường là những thứ chúng ta vô tình ném vào lịch sử (history). Đó có thể là file dump.sql nặng 1GB, folder node_modules bị commit nhầm, hay hàng ngàn tag cũ không bao giờ dùng tới. Git có trí nhớ cực tốt. Nó sẽ lưu giữ những sai lầm đó mãi mãi trừ khi bạn ra tay can thiệp.

Thay vì ngồi mò mẫm từng folder một cách thủ công, mình thường dùng git-sizer. Đây là “vũ khí hạng nặng” giúp khám bệnh và chỉ đích danh những thành phần đang làm tạ cho repo của bạn.

Git-sizer là gì và tại sao nó khác biệt?

Thông thường, anh em hay dùng lệnh du -sh .git để kiểm tra dung lượng. Tuy nhiên, con số tổng quát này không giúp bạn biết tại sao repo lại nặng.

Điểm ăn tiền của git-sizer là khả năng bóc tách cấu trúc bên trong của Git như objects, trees, blobs và commits. Nó tính toán các chỉ số quan trọng bao gồm:

  • Tổng số lượng commit và kích thước tối đa của một commit đơn lẻ.
  • Danh sách các blob (file) chiếm dung lượng lớn nhất.
  • Độ sâu của cây thư mục (tree depth).
  • Số lượng reference (như branches và tags) đang tồn tại.

Công cụ này đánh giá repo theo thang điểm từ 0 đến 30+ sao. Càng nhiều sao, repo của bạn càng có nguy cơ bị các server như GitHub từ chối hoặc khiến máy đồng nghiệp chạy chậm như rùa.

Cài đặt git-sizer

Việc cài đặt rất nhanh vì đây là một file thực thi duy nhất được viết bằng Go. Với người dùng macOS đã có Homebrew, bạn chỉ cần chạy:

brew install git-sizer

Nếu dùng Windows hoặc Linux, bạn hãy tải bản build sẵn từ trang Releases của GitHub rồi cho vào PATH. Ngoài ra, nếu máy đã cài sẵn Go, bạn có thể cài trực tiếp qua lệnh:

go install github.com/github/git-sizer@latest

Thực hành: Phân tích một repo “có vấn đề”

Để bắt đầu, hãy di chuyển vào thư mục repo đang bị phình to và chạy lệnh:

git-sizer --verbose

Tham số --verbose sẽ liệt kê chi tiết các file cụ thể. Dưới đây là kết quả thực tế từ một dự án legacy mình từng tối ưu:


| Name                         | Value     | Level of concern               |
| ---------------------------- | --------- | ------------------------------ |
| Overall repository size      |           |                                |
| * Total size of blobs        |  1.52 GiB | *                              |
| * Total size of trees        |  85.2 MiB |                                |
| * Total size of commits      |  12.4 MiB |                                |
|                              |           |                                |
| Biggest objects              |           |                                |
| * Maximum blob size          |   450 MiB | ******************** (20 stars)|
| * Maximum tree size          |   1.2 MiB | **                             |
|                              |           |                                |
| History structure            |           |                                |
| * Maximum commit depth       |    15,402 | ****                           |

Dòng Maximum blob size nhận tới 20 sao là một dấu hiệu báo động đỏ. Nó cho thấy có ít nhất một file nặng tới 450MB đang ẩn mình trong lịch sử. Dù bạn đã xóa file đó ở commit hiện tại, Git vẫn giữ nó trong .git để đảm bảo khả năng checkout về quá khứ.

Truy tìm thủ phạm

Khi đã biết có file lớn, mình thường dùng lệnh sau để tìm chính xác tên file đó:

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print $1}')"

Lệnh này sẽ khớp các ID từ git-sizer với tên file thực tế. Trong một dự án thực tế, mình từng phát hiện một bạn dev vô tình commit file video_demo.mp4 nặng 600MB. Việc biết đích danh file giúp quá trình dọn dẹp diễn ra cực kỳ nhanh chóng.

Cách tối ưu hóa sau khi phân tích

Bạn không thể chỉ dùng rm file rồi git commit để giải quyết vấn đề này. Bạn cần phải “phẫu thuật” lại toàn bộ lịch sử Git.

1. Sử dụng git-filter-repo (Lựa chọn tốt nhất)

Đây là công cụ hiện đại, an toàn và nhanh hơn nhiều so với git filter-branch đã lỗi thời. Để xóa vĩnh viễn một file nặng khỏi lịch sử, hãy dùng:

git filter-repo --path path/to/large/file --invert-paths

Lưu ý quan trọng: Thao tác này sẽ thay đổi mã hash của các commit cũ. Bạn bắt buộc phải thông báo để cả team clone lại repo mới sau khi dọn dẹp.

2. Dọn dẹp các reference dư thừa

Nếu git-sizer báo lỗi ở phần Total number of references, repo của bạn đang có quá nhiều branch và tag rác. Hãy xóa các branch đã merge vào main bằng lệnh:

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Kinh nghiệm để giữ repo luôn “xanh”

Dọn dẹp một repo nặng vài GB là một cực hình. Để tránh lặp lại sai lầm, mình luôn áp dụng 3 quy tắc thép cho team:

  • Thiết lập .gitignore chuẩn: Chặn triệt để log, build artifacts và các thư mục dependency như node_modules ngay từ ngày đầu.
  • Sử dụng Git LFS: Nếu dự án bắt buộc phải chứa file lớn như model AI hay ảnh 4K, hãy dùng Git LFS thay vì commit trực tiếp.
  • Kiểm tra định kỳ: Cứ mỗi 3 tháng, hãy chạy git-sizer một lần trên nhánh chính để phát hiện sớm các file “đi lạc”.

Sau khi áp dụng quy trình này, tốc độ CI/CD của team mình đã cải thiện rõ rệt. Thời gian fetch code về server build giảm từ 5 phút xuống còn chưa đầy 30 giây.

Lời kết

Git-sizer không trực tiếp sửa lỗi, nhưng nó là chiếc kính hiển vi giúp bạn nhìn thấu mọi vấn đề tiềm ẩn. Đừng đợi đến khi repo nặng tới mức không thể clone nổi mới bắt đầu lo lắng. Hãy thử chạy git-sizer ngay hôm nay, kết quả có thể sẽ khiến bạn bất ngờ đấy!

Share: