31

Tôi có một repo git với một số tệp nhị phân rất lớn trong đó. Tôi không còn cần chúng nữa, và tôi không quan tâm đến việc có thể kiểm tra các tập tin từ các cam kết trước đó. Vì vậy, để giảm kích thước repo, tôi muốn xóa các tệp nhị phân khỏi lịch sử hoàn toàn.Cập nhật nhóm phát triển với lịch sử repo Git được viết lại, xóa các tệp lớn

Sau khi tìm kiếm web, tôi kết luận rằng (chỉ?) Lựa chọn tốt nhất của tôi là sử dụng git-filter-branch:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' HEAD 

Điều này có vẻ giống như một cách tiếp cận tốt cho đến nay?

Giả sử câu trả lời là có, tôi có một vấn đề khác để tranh luận. The git manual has this warning:

CẢNH BÁO! Lịch sử viết lại sẽ có tên đối tượng khác nhau cho tất cả các đối tượng và sẽ không hội tụ với nhánh ban đầu. Bạn sẽ không thể dễ dàng đẩy và phân phối nhánh viết lại trên đầu nhánh gốc. Xin vui lòng không sử dụng lệnh này nếu bạn không biết đầy đủ ý nghĩa, và tránh sử dụng nó anyway, nếu một cam kết đơn giản sẽ đủ để sửa chữa vấn đề của bạn. (Xem phần "RECOVERING FROM UPSTREAM REBASE" trong git-rebase (1) để biết thêm thông tin về việc viết lại lịch sử đã xuất bản.)

Chúng tôi có một repo từ xa trên máy chủ của chúng tôi. Mỗi nhà phát triển đẩy và kéo từ nó. Dựa trên các cảnh báo trên (và sự hiểu biết của tôi về cách git-filter-branch hoạt động), tôi không nghĩ rằng tôi sẽ có thể chạy git-filter-branch trên bản sao cục bộ của tôi và sau đó đẩy các thay đổi.

Vì vậy, tôi đang dự kiến ​​kế hoạch để đi qua các bước sau:

  1. thiệu với tất cả các nhà phát triển của tôi để cam kết, đẩy, và ngừng làm việc cho một chút.
  2. Đăng nhập vào máy chủ và chạy bộ lọc trên repo trung tâm.
  3. Yêu cầu mọi người xóa các bản sao cũ của họ và sao chép lại từ máy chủ.

Điều này có đúng không? Đây có phải là giải pháp tốt nhất không?

+2

Nó xảy ra với tôi bây giờ mà các * đơn giản nhất * điều cần làm có thể là để có các nhà phát triển của bạn mỗi chạy lệnh 'git-filter-branch' giống hệt nhau. Họ nên kết thúc với lịch sử giống hệt với những gì bạn tạo ra mà không cần phải sao chép lại hoặc tự rebase. –

+1

@BenJackson các tệp mã sẽ giống hệt nhau, nhưng các đối tượng cam kết sẽ có siêu dữ liệu dấu cộng khác nhau được thêm vào bởi quá trình rebase. – Douglas

+1

@Douglas Tôi không nghĩ rằng 'git filter-branch' sẽ thay đổi dữ liệu của người gửi trừ khi bạn yêu cầu nó một cách rõ ràng. ('git commit --rebase' hiện, nhưng không phải là' git filter-branch', như tôi thấy.) – cdhowie

Trả lời

18

Có, giải pháp của bạn sẽ hoạt động. Bạn cũng có một tùy chọn khác: thay vì làm điều này trên repo trung tâm, chạy bộ lọc trên bản sao của bạn và sau đó đẩy nó trở lại với git push --force --all. Điều này sẽ buộc máy chủ chấp nhận các chi nhánh mới từ kho lưu trữ của bạn. Điều này chỉ thay thế bước 2; các bước khác sẽ giống nhau.

Nếu nhà phát triển của bạn khá hiểu biết, thì họ có thể không phải xóa các bản sao cũ của họ; ví dụ, họ có thể tìm nạp các điều khiển từ xa mới và rebase các nhánh chủ đề của họ khi thích hợp.

+0

Điều này không xem xét tất cả các trường hợp. Nếu có thẻ hoặc các nhánh khác, tất cả bạn nên '--tag-name-filter cat' và' - --all' thay vì HEAD thành các tùy chọn git filter-branch. Xem câu trả lời của tôi để biết thêm thông tin. –

5

Nếu bạn không làm cho các nhà phát triển của bạn sao chép lại, có khả năng họ sẽ quản lý để kéo các tệp lớn trở lại. Ví dụ: nếu chúng gắn chặt vào lịch sử mới, bạn sẽ tạo và sau đó xảy ra git merge từ chi nhánh dự án địa phương không được rebased, cha mẹ của cam kết hợp nhất sẽ bao gồm các chi nhánh dự án mà cuối cùng chỉ vào toàn bộ lịch sử bạn bị xóa với git filter-branch.

+0

Vì vậy, nói cách khác, kế hoạch của tôi để có tất cả mọi người sao chép lại sẽ tránh được rất nhiều gotchas tiềm năng? – rlkw1024

+1

Dành cho bạn và kho lưu trữ.Nó sẽ gây phiền nhiễu cho bất cứ ai có một bộ sưu tập trước của các chi nhánh dự án và stashes. –

9

Kế hoạch của bạn tốt (mặc dù sẽ tốt hơn nếu thực hiện lọc trên bản sao kho lưu trữ của bạn, thay vì trên máy chủ trung tâm), nhưng ưu tiên git-filter-branch bạn nên sử dụng số BFG Repo-Cleaner của mình. đến git-filter-branch được thiết kế đặc biệt để xóa các tệp lớn từ Git repos.

Tải the Java jar (yêu cầu Java 6 hoặc cao hơn) và chạy lệnh này:

$ java -jar bfg.jar --strip-blobs-bigger-than 1MB my-repo.git 

Bất kỳ blob hơn 1MB kích thước (không có trong bạn mới nhất cam) sẽ hoàn toàn loại bỏ từ lịch sử của kho lưu trữ của bạn. Sau đó bạn có thể sử dụng git gc để làm sạch đi những dữ liệu chết:

$ git gc --prune=now --aggressive 

BFG thường 10-50x nhanh hơn chạy git-filter-branch và các tùy chọn được thiết kế xung quanh hai chung trường hợp sử dụng:

  • Loại bỏ điên Big tập tin
  • Loại bỏ Passwords, Credentials & dữ liệu cá nhân khác
3

Giải pháp của bạn chưa hoàn thành. Bạn nên bao gồm --tag-name-filter cat làm đối số để lọc chi nhánh để các thẻ chứa các tệp lớn cũng được thay đổi. Bạn cũng nên sửa đổi tất cả các thay đổi thay vì chỉ HEAD vì cam kết có thể ở nhiều nhánh.

Dưới đây là một số mã tốt hơn:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' --tag-name-filter cat -- --all 

Github có một hướng dẫn tốt: https://help.github.com/articles/remove-sensitive-data

Các vấn đề liên quan