2012-01-05 40 views
85

Tôi cam kết với id 56f06019 (ví dụ). Trong cam kết đó tôi đã vô tình cam kết tệp lớn (50Mb). Trong cam kết khác tôi thêm cùng một tệp nhưng ở kích thước phù hợp (nhỏ). Bây giờ repo của tôi khi tôi sao chép là quá nặng :(Làm thế nào để loại bỏ tập tin lớn từ lịch sử repo để giảm kích thước của repo của tôiGit: Cách xóa tệp khỏi cam kết lịch sử?

+0

trong trường hợp của tôi, nó không phải là tệp lớn, nhưng tệp cấu hình chứa tín dụng cơ sở dữ liệu. Tôi đã học git, lúc đó tôi không biết về .gitignore. – Rashi

+0

bản sao có thể có của [Cách xóa/xóa một tệp lớn khỏi lịch sử cam kết trong kho Git?] (Http: // stackoverflow.com/questions/2100907/how-to-remove-delete-a-large-file-từ-commit-history-in-git-repository) –

Trả lời

123

Chương 9 của sách Pro Git có một phần trên Removing Objects.

Hãy để tôi phác thảo các bước ngắn gọn ở đây:

git filter-branch --index-filter \ 
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \ 
    --tag-name-filter cat -- --all 

Giống như tùy chọn rebasing được mô tả trước đây, filter-branch được viết lại hoạt động. Nếu bạn đã xuất bản lịch sử, bạn sẽ phải --force đẩy các tham chiếu mới.

Cách tiếp cận filter-branch là đáng kể mạnh hơn so với phương pháp rebase, vì nó

  • cho phép bạn làm việc trên tất cả các chi nhánh/refs cùng một lúc,
  • đổi tên bất kỳ thẻ khi đang bay
  • hoạt động sạch ngay cả khi đã có một số cam kết hợp nhất kể từ khi thêm tệp
  • hoạt động sạch ngay cả khi tệp (lại) được thêm/xóa nhiều lần trong lịch sử (a) chi nhánh
  • không tạo ra các cam kết mới, không liên quan, mà là sao chép chúng trong khi sửa đổi các cây liên kết với chúng. Điều này có nghĩa rằng những thứ như các cam kết đã ký, cam kết ghi chú vv được bảo quản

filter-branch giữ sao lưu quá, vì vậy kích thước của repo sẽ không giảm ngay lập tức trừ khi bạn hết hạn reflogs và rác thu thập:

rm -Rf .git/refs/original  # careful 
git gc --aggressive --prune=now # danger 
+1

Cần lưu ý rằng điều này dường như không hoạt động trong cửa sổ cmd.exe. Dường như làm việc theo Cygwin tốt, mặc dù. –

+1

Tôi đã nhận bộ lọc git ở trên để làm việc bằng cách sử dụng dấu ngoặc kép thay vì dấu nháy đơn (trên Windows Server 2012 cmd.exe) – JCii

+0

Điều gì đã làm việc cho tôi là dòng lệnh bộ lọc nhánh này. 'git filter-branch --force --index-filter' git rm --ignore-unmatch --cách PathTo/MyFile/ToRemove.dll '- fbf28b005^.. ' Sau đó ' rm --recursive - -force .git/refs/original' và 'rm --recursive --force .git/logs' Sau đó, tôi đã sử dụng' git prune --expire now' và 'git gc --aggressive' tốt hơn cho tôi hơn các bước chính xác của bạn được liệt kê ở trên. Cảm ơn bạn đã bao gồm các liên kết đến cuốn sách Git Pro vì nó là vô giá. –

1

Bạn sẽ cần phải git rebase ở chế độ tương tác xem một ví dụ ở đây:? How can I remove a commit on GitHub?how to remove old commits.

Nếu bạn cam kết là TRỤ trừ 10 cam kết:

$ git rebase -i HEAD~10 

Sau khi phiên bản của lịch sử của bạn, bạn cần phải đẩy "mới" lịch sử, bạn cần phải thêm + để buộc (xem refspec trong số push options):

$ git push origin +master 

Nếu người khác đã nhân bản kho lưu trữ của bạn, bạn sẽ thông báo cho họ, vì bạn vừa thay đổi lịch sử.

+3

Điều đó không ** xóa ** tệp lớn khỏi lịch sử. Ngoài ra, cách kinh điển để ép buộc là 'git push - force' hoặc' git push -f' (không yêu cầu mọi người biết mục tiêu đẩy nhánh) – sehe

+0

Dựa trên câu hỏi, tệp mới hoàn toàn giống nhau là tệp cũ, có nghĩa là, cùng một đường dẫn. Đây là lý do tại sao bạn không thể trực tiếp sử dụng 'git rm' trên đường dẫn. –

+2

@sehe, nếu bạn thực hiện việc rebase loại bỏ cam kết với tệp lớn, nó sẽ biến mất. – vonbrand

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