Xóa tệp khỏi kho Git mà không xóa tệp khỏi hệ thống tệp cục bộ


3047

Cam kết ban đầu của tôi có chứa một số tệp nhật ký. Tôi đã thêm *logvào của tôi .gitignore, và bây giờ tôi muốn loại bỏ các tập tin log từ kho lưu trữ của tôi.

git rm mylogfile.log

sẽ xóa một tệp khỏi kho lưu trữ, nhưng cũng sẽ xóa nó khỏi hệ thống tệp cục bộ.

Làm cách nào tôi có thể xóa tệp này khỏi repo mà không xóa bản sao cục bộ của tệp?



14
Điều đáng chú ý là câu trả lời được đánh giá cao nhất là nguy hiểm đối với một số người. Nếu bạn đang sử dụng repo từ xa so với khi bạn đẩy cục bộ của mình thì hãy kéo các tệp khác mà bạn đã xóa khỏi git chỉ S W BỊ XÓA . Điều này được đề cập trong một trong những câu trả lời nhưng không được bình luận.
RichieHH

Câu trả lời:


4354

Từ tập tin người đàn ông :

Khi --cachedđược đưa ra, nội dung theo giai đoạn phải khớp với đầu của nhánh hoặc tệp trên đĩa, cho phép xóa tệp khỏi chỉ mục.

Vì vậy, đối với một tệp duy nhất:

git rm --cached mylogfile.log

và cho một thư mục duy nhất:

git rm --cached -r mydirectory

151
Dễ dàng bỏ qua vì nó không phải là tự giải thích như svn rm --keep-local.
Martin

114
Nhưng làm thế nào để tôi bảo quản các tập tin trên các máy chủ từ xa? Điều này giữ cho máy cục bộ của tôi, nhưng nếu tôi đẩy và kéo từ máy chủ khác, tệp sẽ bị xóa. Tôi cũng đã thêm một .gitignore cho tệp, nhưng nó vẫn bị xóa
spankmaster79

6
Việc này vẫn xóa các tệp trên git pullnếu bạn đứng sau cam kết saugit rm
Petr Peller

9
Đáng lưu ý rằng, sau khi chạy lệnh trong câu trả lời, bạn cần sử dụng git commit -m "Commit message"git push. Nếu bạn có bất kỳ thay đổi theo giai đoạn nào khác (kiểm tra với git status), chúng cũng sẽ được cam kết tại thời điểm này.
Sinjai

9
Vì đây là câu trả lời được chấp nhận nhiều nhất và không làm, nên những gì được yêu cầu, tôi sẽ nói tôi làm gì. Tôi sử dụng lệnh git rm --cached mylogfile.logvà xóa các tập tin từ kho lưu trữ. Để tránh mất tập tin trên hệ thống sản xuất, tôi thực hiện sao lưu tập tin và kéo theo sau. Tệp bị xóa như đã đề cập trước đó và cần được sao chép lại từ bản sao lưu của bạn. Đây là một nỗi đau, nhưng tôi không tìm thấy giải pháp nào tốt hơn cho vấn đề này.
Marcel Grolms

275

Để xóa toàn bộ thư mục khỏi repo (như tệp Resharper), hãy làm điều này:

git rm -r --cached folderName

Tôi đã cam kết một số tệp chia sẻ lại và không muốn chúng tồn tại cho những người dùng dự án khác.


13
Chỉ là một lưu ý bổ sung cho khách truy cập trong tương lai: Không sử dụng GUI để "Đồng bộ hóa" cam kết trở lại repo. Điều đó sẽ kéo các tập tin trở lại vào repo cục bộ của bạn. Bạn phải làm một Git Push repo branchđể thực sự loại bỏ các tập tin từ xa.
RubberDuck

211

Bạn cũng có thể xóa các tệp khỏi kho lưu trữ dựa trên .gitignore của bạn mà không xóa chúng khỏi hệ thống tệp cục bộ:

git rm --cached `git ls-files -i -X .gitignore`

Hoặc, cách khác, trên Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)

7
Không hoạt động trên Windows. git ls-files -i -X ​​.gitignore hoạt động, nhưng tôi không biết làm cách nào để gửi các tệp đến 'git rm'. Bạn có biết làm thế nào để làm điều đó?
Erik Z

17
Hoạt động trên Windows nếu bạn sử dụng Git Bash thay vì cmd-console
Andreas Zita

17
Thích cái này. Làm việc ngoại trừ tôi có một số tệp cuối cùng có khoảng trắng trong tên tệp. Tôi đã sửa đổi giải pháp ở đây để : git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}". Vui lòng xem xét sửa đổi hoặc thêm giải pháp này vào câu trả lời ở đây, bởi vì đây là một công cụ tuyệt vời để có ...
mpettis

Tôi đã không thử nhưng cần kiểm tra xem nó có xóa các tệp như .gitkeepbảo quản một thư mục trống trong kho không. Ví dụ. .gitignorechứa thư mục uploadsvà repo buộc phải theo dõi .gitkeep. Bằng cách loại bỏ tất cả từ repo dưới uploadsnó cũng sẽ loại bỏ .gitkeep.
Vladimir Vukanac

Đề xuất này hoạt động hoàn hảo trong powershell: git rm --cached $ (git ls-files -i -X ​​.gitignore)
geekandglitter

89

Theo câu trả lời của tôi ở đây: /programming/6313126/how-to-remove-a-directory-in-my-github-reposeective

Để xóa thư mục / thư mục hoặc tệp chỉ từ kho git chứ không xóa khỏi cục bộ, hãy thử 3 bước đơn giản.


Các bước để loại bỏ thư mục

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Các bước để bỏ qua thư mục đó trong các lần xác nhận tiếp theo

Để bỏ qua thư mục đó từ các lần xác nhận tiếp theo, hãy tạo một tệp trong thư mục gốc có tên .gitignore và đặt tên thư mục đó vào đó. Bạn có thể đặt bao nhiêu tùy thích

tập tin .gitignore sẽ trông như thế này

/FolderName

xóa thư mục


@gaurav rất vui vì nó đã giúp!
eirenaios

69

Ngoài ra, nếu bạn đã cam kết dữ liệu nhạy cảm (ví dụ: tệp chứa mật khẩu), bạn nên xóa hoàn toàn dữ liệu đó khỏi lịch sử của kho lưu trữ. Dưới đây là hướng dẫn giải thích cách thực hiện: http://help.github.com/remove-sensitive-data/


13
Câu trả lời này nên bao gồm các lệnh cần thiết để hoàn thành nhiệm vụ này thay vì liên kết đến một trang web khác.
Florian Lemaitre

1
Tôi cũng sẽ lưu ý rằng tôi đã tìm thấy bằng cách sử dụng công cụ dọn dẹp git bfg repo dễ dàng và nhanh hơn.
lubed lên Slug

64

Một giải pháp chung hơn:

  1. Chỉnh sửa .gitignoretập tin.

    ECHO mylogfile.log >> .gitignore

  2. Xóa tất cả các mục khỏi chỉ mục.

    git rm -r -f --cached .

  3. Xây dựng lại chỉ số.

    git add .

  4. Thực hiện cam kết mới

    git commit -m "Removed mylogfile.log"


2
Điều này thực sự sẽ xóa các tập tin?
Mr_and_Mrs_D 13/12/13

6
Từ GitHub? KHÔNG. Nếu bạn đã đẩy lên github, nó sẽ không xóa nó khỏi trang web. Nhưng nó sẽ cập nhật kho git cục bộ của bạn.
mAsT3RpEE

5
Nhận xét bạn đã xóa thực sự bị loại bỏ hơn :) Vấn đề với giải pháp rm --cashedlà cuối cùng nó sẽ xóa tệp khi một lần kéo - phải không? Và đây không phải là điều mọi người muốn khi họ nói "Xóa một tệp khỏi kho lưu trữ mà không xóa nó khỏi hệ thống tệp cục bộ ". Bây giờ tại sao giải pháp trên được chấp nhận lại nằm ngoài tôi - có lẽ OP đã làm việc một mình và không bao giờ kéo? Không biết. Tôi hiểu vấn đề về github "một lần luôn luôn có"
Mr_and_Mrs_D 14/12/13

Tôi không nghĩ có một giải pháp 100% trừ khi bạn hỏi chính github. Để bây giờ dính vào điều này. Sao chép tệp, Thêm vào gitignore, thực hiện git rm -r, cam kết, đẩy, khôi phục tệp. Bạn đã quản lý để tìm một giải pháp khác?
mAsT3RpEE

9
Vấn đề của tôi không phải là github - đó là tập tin thực sự sẽ bị xóa khỏi đồng nghiệp khi họ kéo . Tôi không muốn xóa tập tin. Điều này đã gây ra cho tôi những vấn đề lớn trong quá khứ. Vì vậy, tôi đã tự hỏi nếu thực sự có một giải pháp mà thực sự không xóa các tập tin. Xem thêm bình luận quán trọ câu trả lời được chấp nhận: stackoverflow.com/questions/1143796/
Khăn

24

Git cho phép bạn bỏ qua các tệp đó bằng cách giả sử chúng không thay đổi. Điều này được thực hiện bằng cách chạy git update-index --assume-unchanged path/to/file.txtlệnh. Sau khi đánh dấu một tệp như vậy, git sẽ hoàn toàn bỏ qua mọi thay đổi trên tệp đó; chúng sẽ không hiển thị khi chạy trạng thái git hoặc git diff, và chúng sẽ không bao giờ được cam kết.

(Từ https://help.github.com/articles/ignoring-files )

Do đó, không xóa nó, mà bỏ qua những thay đổi mãi mãi. Tôi nghĩ rằng điều này chỉ hoạt động tại địa phương, vì vậy đồng nghiệp vẫn có thể thấy các thay đổi đối với nó trừ khi họ chạy cùng một lệnh như trên. (Vẫn cần xác minh điều này.)

Lưu ý: Điều này không trả lời trực tiếp câu hỏi, nhưng dựa trên các câu hỏi tiếp theo trong các bình luận của các câu trả lời khác.


2
Hừm, tôi làm điều này nhưng tôi thấy rằng tập tin có thể bị ghi đè nếu có người khác thay đổi nó trên repo.
AlxVallejo

17

Nếu bạn muốn chỉ mở khóa một tệp và không xóa khỏi repo cục bộ và từ xa thì hãy sử dụng lệnh này:

git update-index --assume-unchanged  file_name_with_path

2
Mặc dù đây là một câu trả lời hay, nhưng điều quan trọng cần lưu ý là đây không "bẻ khóa" một tệp theo nghĩa mọi người thường sử dụng từ đó với Git, trong đó một tệp không bị theo dõi là một tệp không có trong lịch sử kho lưu trữ và chưa bao giờ . Điều mà câu trả lời này làm là giữ tệp trong kho lưu trữ nhưng ngăn Git nhận thấy những thay đổi đã được thực hiện đối với nó. Điều đó có một số khác biệt đáng kể - quan trọng nhất là tệp vẫn còn cho người khác và nếu người khác thay đổi nó và bạn kéo, bản sao cục bộ của bạn có thể bị ghi đè mà không cần xác nhận.
Soren Bjornstad

8

Câu trả lời trên không làm việc cho tôi. Tôi đã sử dụngfilter-branch để loại bỏ tất cả các tập tin cam kết.

Xóa tệp khỏi kho git với:

git filter-branch --tree-filter 'rm  file'

Xóa thư mục khỏi kho git với:

git filter-branch --tree-filter 'rm -rf directory'

Điều này loại bỏ thư mục hoặc tập tin từ tất cả các cam kết.

Bạn có thể chỉ định một cam kết bằng cách sử dụng:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Hoặc một phạm vi:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

Để đẩy mọi thứ đến từ xa, bạn có thể làm:

git push origin master --force

2
Điều này kết hợp với git rm -r --cached NAMElà mẹo để xóa nó khỏi repo git cục bộ của bạn và ngăn nó ảnh hưởng đến bất kỳ ai kéo về sau (bằng cách xóa lịch sử của tệp hoặc thư mục khỏi git.)
notbad.jpeg 17/03/2016

1
Điều này viết lại lịch sử git và bạn sẽ cần phải đẩy - lực lượng sau, đây là một chút ngoài phạm vi với câu hỏi tôi đoán. Trên một repo nổi tiếng công khai, bạn không thể thay đổi dòng lịch sử như thế vì mọi người đã nhân bản repo sẽ gặp vấn đề khi kéo.
Guillaume Perrot

0

Bỏ qua các tập tin, loại bỏ các tập tin từ git, cập nhật git (để loại bỏ).

Lưu ý: điều này không liên quan đến lịch sử cho thông tin nhạy cảm.

Quá trình này chắc chắn có một số cam kết về những gì đang xảy ra với git. Theo thời gian, có được điều đó, tôi đã học được cách thực hiện các quy trình như:

1) Bỏ qua các tập tin

  • Thêm hoặc cập nhật dự án .gitignoređể bỏ qua chúng - trong nhiều trường hợp như của bạn, thư mục mẹ, vdlog/ sẽ là regex để sử dụng.
  • cam kết và đẩy .gitignorethay đổi tập tin đó (không chắc chắn nếu bạn cần đẩy tâm trí, không có hại nếu thực hiện).

2) Loại bỏ các tập tin từ git (chỉ).

  • Bây giờ xóa các tệp khỏi git (chỉ) với git remove --cached some_dir/
  • Kiểm tra xem họ vẫn còn ở địa phương (họ nên!).

3) Thêm và cam kết thay đổi đó (về cơ bản đây là thay đổi để "thêm" xóa nội dung, mặc dù lệnh "thêm" khó hiểu khác!)

  • git add .
  • git commit -m"removal"
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.