Câu trả lời được chấp nhận không "làm cho Git " quên " về một tệp ..." (theo lịch sử). Nó chỉ làm cho git bỏ qua các tập tin trong hiện tại / tương lai.
Phương pháp này làm cho git hoàn toàn quên các tệp bị bỏ qua ( quá khứ / hiện tại / tương lai), nhưng không xóa bất cứ thứ gì khỏi thư mục làm việc (ngay cả khi được kéo lại từ xa).
Phương pháp này yêu cầu sử dụng /.git/info/exclude
(ưu tiên) hoặc một tồn tại trước đó .gitignore
trong tất cả các cam kết đó có các tập tin để được bỏ qua / lãng quên. 1
Tất cả các phương pháp thực thi git bỏ qua hành vi sau khi thực tế viết lại lịch sử một cách hiệu quả và do đó có sự phân nhánh đáng kể cho bất kỳ repos công khai / chia sẻ / hợp tác nào có thể được rút ra sau quá trình này. 2
Lời khuyên chung: bắt đầu với một repo sạch - mọi thứ đã cam kết, không có gì đang chờ xử lý trong thư mục hoặc chỉ mục làm việc và tạo bản sao lưu !
Ngoài ra, lịch sử bình luận / sửa đổi của câu trả lời này ( và lịch sử sửa đổi của câu hỏi này ) có thể hữu ích / khai sáng.
#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"
#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached
#Commit to prevent working directory data loss!
#this commit will be automatically deleted by the --prune-empty flag in the following command
#this command must be run on each branch
git commit -m "ignored index"
#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits. If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command
git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all
#List all still-existing files that are now ignored properly
#if this command returns nothing, it's time to restore from backup and start over
#this command must be run on each branch
git ls-files --other --ignored --exclude-standard
Cuối cùng, hãy làm theo phần còn lại của hướng dẫn GitHub này (bắt đầu từ bước 6) bao gồm các cảnh báo / thông tin quan trọng về các lệnh bên dưới .
git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
Các nhà phát triển khác lấy từ repo từ xa đã sửa đổi nên tạo bản sao lưu và sau đó:
#fetch modified remote
git fetch --all
#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed
git reset FETCH_HEAD
Chú thích
1 Vì /.git/info/exclude
có thể được áp dụng cho tất cả các cam kết lịch sử bằng cách sử dụng các hướng dẫn ở trên, có lẽ chi tiết về việc đưa .gitignore
tệp vào (các) cam kết lịch sử cần nó nằm ngoài phạm vi của câu trả lời này. Tôi muốn có một quyền thích hợp .gitignore
trong cam kết gốc, như thể đó là điều đầu tiên tôi làm. Những người khác có thể không quan tâm vì /.git/info/exclude
có thể hoàn thành điều tương tự bất kể nơi .gitignore
nào tồn tại trong lịch sử cam kết và rõ ràng viết lại lịch sử là một chủ đề rất cảm động, ngay cả khi nhận thức được sự phân nhánh .
FWIW, các phương thức tiềm năng có thể bao gồm git rebase
hoặc một git filter-branch
bản sao bên ngoài .gitignore
vào mỗi cam kết, như câu trả lời cho câu hỏi này
2 Thực thi hành vi bỏ qua git sau thực tế bằng cách cam kết kết quả của một git rm --cached
lệnh độc lập có thể dẫn đến việc xóa tệp mới bị bỏ qua trong các lần kéo trong tương lai từ điều khiển từ xa bị đẩy. Các --prune-empty
cờ trong những điều sau git filter-branch
lệnh tránh vấn đề này bằng cách tự động loại bỏ trước đó "xóa tất cả các file phớt lờ" chỉ số chỉ cam kết. Viết lại lịch sử git cũng thay đổi băm cam kết, điều này sẽ tàn phá những lần kéo trong tương lai từ các repos công khai / chia sẻ / hợp tác. Hãy hiểu sự phân nhánh đầy đủ trước khi làm điều này với một repo như vậy. Hướng dẫn GitHub này chỉ định như sau:
Nói với các cộng tác viên của bạn để rebase , không hợp nhất, bất kỳ chi nhánh nào họ tạo ra từ lịch sử kho lưu trữ cũ (bị nhiễm độc) của bạn. Một cam kết hợp nhất có thể giới thiệu lại một số hoặc tất cả lịch sử bị ô nhiễm mà bạn vừa gặp rắc rối với việc thanh trừng.
Các giải pháp thay thế không ảnh hưởng đến repo từ xa là git update-index --assume-unchanged </path/file>
hoặc git update-index --skip-worktree <file>
, ví dụ có thể tìm thấy ở đây .
git clean -X
Nghe có vẻ tương tự, nhưng nó không áp dụng trong tình huống này (khi các tệp vẫn đang được Git theo dõi). Tôi đang viết điều này cho bất cứ ai đang tìm kiếm một giải pháp không đi sai tuyến đường.