Làm cách nào để xóa tệp khỏi lịch sử Git?


88

Cách đây một thời gian, tôi đã thêm thông tin (tệp) phải ở chế độ riêng tư. Xóa khỏi dự án không phải là vấn đề, nhưng tôi cũng cần xóa nó khỏi gitlịch sử.

Tôi sử dụng Git và Github (tài khoản riêng).

Lưu ý: Trong luồng này, một cái gì đó tương tự cũng hiển thị, nhưng đây là một tệp cũ đã được thêm vào một nhánh tính năng, nhánh đó được hợp nhất với một nhánh phát triển và cuối cùng được hợp nhất để làm chủ, vì điều này, rất nhiều thay đổi đã được thực hiện. Vì vậy, nó không giống nhau và điều cần thiết là thay đổi lịch sử và ẩn các tệp đó để bảo mật.


3
Bạn sẽ phải viết lại lịch sử. Ví dụ git rebasesau đógit push -f
Cory Kramer


Các filter-branchphương pháp được mô tả trong bản sao gợi ý sẽ làm những gì bạn muốn.
1615903

Ngoài ra stackoverflow.com/a/17890278 trỏ đến BFG có thể nhanh hơn so với việc sử dụnggit filter-branch
Hasturkun

nhưng chỉ cần đi nhanh hơn và làm tương tự, và cần sử dụng java. Tôi đọc @Hasturkun
Marcos R. Guevara

Câu trả lời:


112

Tôi đã tìm thấy câu trả lời này và nó đã giúp:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

Tìm thấy nó ở đây https://myopswork.com/how-remove-files-compleently-from-git-repository-history-47ed3e0c4c35


5
Cảnh báo: Điều này tạo ra rất nhiều cam kết và gây ra sự khác biệt. Bạn có thể phải đẩy mạnh sau đó, nhưng tôi đã quá sợ hãi.
sudo

1
Chấp nhận những gì @sudo đã nói nhưng điều này đã hiệu quả với chi nhánh mới của tôi mà tôi đã vô tình phạm .envphải. Nhanh chóng và giải pháp điểm.
Joe Scotto

1
Thật vậy, một lực đẩy đơn giản hoạt động! Tôi cũng sợ hãi nhưng sao lưu mọi thứ.
wutBruh

1
Bạn cũng có thể chỉ định một phạm vi cam kết làm đối số cuối cùng. Nếu cam kết được đề cập là gần đây, hãy thực hiện <previous_hash>..HEADvà tiết kiệm thời gian.
Victor Sergienko

48

Nếu gần đây bạn đã cam kết tệp đó hoặc nếu tệp đó đã thay đổi trong một hoặc hai lần cam kết, thì tôi khuyên bạn nên sử dụng rebasecherrypickxóa cam kết cụ thể đó.

Nếu không, bạn phải viết lại toàn bộ lịch sử.

git filter-branch --tree-filter 'rm -f <path_to_file>' HEAD

Khi bạn hài lòng với những thay đổi và đã đảm bảo hợp lý rằng mọi thứ đều ổn, bạn cần cập nhật tất cả các nhánh từ xa -

git push origin --force --all

Lưu ý: - Đây là một hoạt động phức tạp và bạn phải nhận thức được những gì bạn đang làm. Trước tiên, hãy thử thực hiện trên kho lưu trữ demo để xem nó hoạt động như thế nào. Bạn cũng cần cho các nhà phát triển khác biết về điều đó, để họ không thực hiện bất kỳ thay đổi nào trong thời gian cần thiết.


Sau khi viết lại toàn bộ lịch sử, để giữ các thay đổi đối với kho lưu trữ (github) bạn phải làm gì?
Marcos R. Guevara

cảm ơn bạn, tôi sẽ đợi để làm điều đó và thử nó với một kho lưu trữ demo, tôi sẽ cập nhật với tất cả những gì đã được thực hiện ở đây.
Marcos R. Guevara

Do nhầm lẫn, tôi đã quên thêm --all. Bây giờ nó cho biết mọi thứ được cập nhật bất cứ khi nào tôi chạy lại push với cả hai đối số. Và tệp không bị xóa khỏi các nhánh khác. Tôi nên làm gì bây giờ?
Reeshabh Ranjan

Tại sao đề xuất của bạn lại sử dụng --tree-filterchứ không phải --index-filternhư trong câu trả lời của @ PetroFranko?
einpoklum

13
  • loại bỏ tệp và ghi lại lịch sử từ cam kết bạn đã thực hiện với tệp đã xóa (điều này sẽ tạo ra băm cam kết mới từ tệp bạn đã cam kết):

    git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' --prune-empty --tag-name-filter cat -- --all

  • bây giờ buộc đẩy repo:

    git push origin --force --all

  • bây giờ yêu cầu các cộng tác viên của bạn rebase.



7
  • Trước hết, hãy thêm nó vào .gitignoretệp của bạn và đừng quên cam kết tệp :-)
  • Bạn có thể sử dụng trang web này: http://gtiignore.io để tạo .gitignorecho bạn và thêm đường dẫn cần thiết vào (các) tệp / thư mục nhị phân của bạn

  • Khi bạn đã thêm tệp vào, .gitignorebạn có thể xóa tệp nhị phân "cũ" bằng BFG.


How to remove big files from the repository

Bạn có thể sử dụng git filter-branchhoặc BFG. https://rtyley.github.io/bfg-repo-cleaner/

BFG Repo-Cleaner

một thay thế cho git-filter-branch.

BFG là một giải pháp thay thế đơn giản hơn, nhanh hơn cho git-filter-branch để làm sạch dữ liệu xấu ra khỏi lịch sử kho lưu trữ Git của bạn:

* Xóa các tệp lớn điên rồ *
* Xóa mật khẩu, thông tin đăng nhập và dữ liệu cá nhân khác

Ví dụ (từ trang chính thức)

Trong tất cả các ví dụ này, bfg là bí danh cho java -jar bfg.jar.

# Delete all files named 'id_rsa' or 'id_dsa' :
bfg --delete-files id_{dsa,rsa}  my-repo.git

nhập mô tả hình ảnh ở đây


6

Tôi đã đọc bài viết GitHub này , dẫn tôi đến lệnh sau (tương tự như câu trả lời được chấp nhận, nhưng mạnh mẽ hơn một chút):

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all

4

git-repo-filter

gitkhuyến nghị sử dụng git-filter-repo (khi git filter-branchlệnh được thực thi). Có một danh sách dài về lý do tại sao nó tốt hơn bất kỳ lựa chọn thay thế nào khác ( https://github.com/newren/git-filter-repo#why-filter-repo-instead-of-other-alternatives ), kinh nghiệm của tôi là nó rất đơn giản và rất nhanh chóng.

Lệnh này xóa tệp khỏi tất cả các cam kết trong tất cả các nhánh:

git filter-repo --path <path to the file or directory> --invert-paths

Nhiều đường dẫn có thể được chỉ định bằng cách sử dụng nhiều --paththam số. Bạn có thể tìm tài liệu chi tiết tại đây: https://www.mankier.com/1/git-filter-repo

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.