Làm cách nào để Gitv quên quên về một tệp đã được theo dõi nhưng hiện đang ở .gitignore?


5401

Có một tệp đang được theo dõi git, nhưng bây giờ tệp này nằm trong .gitignoredanh sách.

Tuy nhiên, tập tin đó tiếp tục hiển thị git statussau khi được chỉnh sửa. Làm thế nào để bạn buộc gitphải hoàn toàn quên nó?


16
git clean -XNghe 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.
imz - Ivan Zakharyaschev 27/2/2015

35
Câu trả lời thực sự duy nhất cho điều này là dưới đây, xem git update-index --assume-unchanged. Giải pháp này 1) giữ tệp trên máy chủ (chỉ mục), 2) cho phép bạn sửa đổi nó một cách tự do cục bộ.
Qwerty

8
Bạn cần sử dụng --skip-worktree, xem: stackoverflow.com/questions/13630849/
Kẻ

77
Một câu hỏi quan trọng là: tập tin có nên lưu trong kho hay không? Ví dụ, nếu ai đó mới nhân bản repo, họ có nên nhận tệp hay không? Nếu thì git update-index --assume-unchanged <file>đúng và tệp sẽ vẫn còn trong kho lưu trữ và các thay đổi sẽ không được thêm vào git add. Nếu KHÔNG (ví dụ: đó là một số tệp bộ đệm, tệp được tạo, v.v.), thì git rm --cached <file>sẽ xóa tệp đó khỏi kho lưu trữ.
Martin

9
@Martin @Qwerty Everyon nên dừng lại để tư vấn cho --assume-unchangedhiệu suất nào để ngăn git kiểm tra trạng thái của các tệp được theo dõi lớn nhưng thích --skip-worktreedùng cho các tệp được theo dõi đã sửa đổi mà người dùng không muốn cam kết nữa. Xem stackoverflow.com/questions/13630849/ từ
Philippe

Câu trả lời:


5704

.gitignoresẽ ngăn các tệp không bị add -ftheo dõi được thêm vào (không có ) vào tập hợp các tệp được theo dõi bởi git, tuy nhiên git sẽ tiếp tục theo dõi bất kỳ tệp nào đã được theo dõi.

Để dừng theo dõi một tập tin, bạn cần xóa nó khỏi chỉ mục. Điều này có thể đạt được với lệnh này.

git rm --cached <file>

Nếu bạn muốn xóa toàn bộ thư mục, bạn cần xóa tất cả các tệp trong đó theo cách đệ quy.

git rm -r --cached <folder>

Việc xóa tệp khỏi bản sửa đổi chính sẽ xảy ra ở lần xác nhận tiếp theo.

CẢNH BÁO: Mặc dù điều này sẽ không xóa tệp vật lý khỏi cục bộ của bạn, nhưng nó sẽ xóa các tệp khỏi các máy phát triển khác tiếp theo git pull.


55
quá trình làm việc với tôi là 1. cam kết thay đổi chờ xử lý trước 2. git rm --cached <file> và cam kết lại 3. thêm tệp vào .gitignore, kiểm tra trạng thái git và cam kết lại
mataal

117
Thêm rất quan trọng. Nếu tập tin bị bỏ qua sẽ được sửa đổi (nhưng mặc dù điều này không nên được cam kết), sau khi sửa đổi và thực thi, git add .nó sẽ được thêm vào chỉ mục. Và cam kết tiếp theo sẽ cam kết nó vào kho lưu trữ. Để tránh điều này thực thi ngay sau khi tất cả những gì mataal nói thêm một lệnh:git update-index --assume-unchanged <path&filename>
Dao

32
Phương pháp của @AkiraYamamoto cũng có hiệu quả với tôi. Trong trường hợp của tôi, tôi đã chặn đầu ra vì kho lưu trữ của tôi có hàng ngàn tệp:git rm -r -q --cached .
Aaron Blenkush

85
Điều này sẽ xóa các tập tin trên git pullmặc dù.
Petr Peller

22
git rm --cached <file> chỉ xóa tệp khỏi kho lưu trữ, git update-index --assume-không thay đổi <file> không hiển thị tệp trong các thay đổi không được sắp xếp và không thực hiện thay đổi mới. Nhưng tôi muốn GIT JUST IGNORE NỘI DUNG FILE PLEEEEEASE
Igor Semin

2610

Một loạt các lệnh dưới đây sẽ xóa tất cả các mục khỏi Chỉ mục Git (không phải từ thư mục làm việc hoặc repo cục bộ), sau đó cập nhật Chỉ mục Git, trong khi tôn trọng git bỏ qua. Tái bút Chỉ mục = Bộ nhớ cache

Đầu tiên:

git rm -r --cached . 
git add .

Sau đó:

git commit -am "Remove ignored files"

Hoặc một lớp lót:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"

197
Để làm nổi bật sự khác biệt giữa câu trả lời này và câu trả lời được chấp nhận: Sử dụng các lệnh này, bạn không cần phải thực sự biết các tệp bị ảnh hưởng. (Hãy tưởng tượng một thư mục tạm thời có nhiều tệp ngẫu nhiên sẽ bị xóa khỏi chỉ mục).
Ludwig

53
Giống như câu trả lời được chấp nhận. Các tập tin sẽ bị xóa trên git pull.
Petr Peller

73
Sẽ thật tuyệt nếu có điều này như một lệnh git tiêu chuẩn. Một cái gì đó như git rmignored.
Berik

12
@gudthing -r là viết tắt của "đệ quy"
Đánh dấu

14
Với điều này, bạn có thể sẽ thêm các tệp vô dụng khác hiện không có trong đó .gitignore. Điều này có thể khó tìm ra nếu tùy thuộc vào mức độ nhiễu của bạn git statussau lệnh này. Một lệnh chỉ loại bỏ các tập tin mới bỏ qua sẽ tốt hơn. Đó là lý do tại sao tôi thích câu trả lời của thSoft
KurzingMetal

1122

git update-index thực hiện công việc cho tôi:

git update-index --assume-unchanged <file>

Lưu ý: Giải pháp này thực sự độc lập .gitignorevì gitignore chỉ dành cho các tệp không bị theo dõi.

chỉnh sửa: Vì câu trả lời này đã được đăng, một tùy chọn mới đã được tạo và nên được ưu tiên hơn. Bạn nên sử dụng --skip-worktreetệp dành cho các tệp được theo dõi đã sửa đổi mà người dùng không muốn cam kết nữa và giữ --assume-unchangedhiệu suất để ngăn git kiểm tra trạng thái của các tệp được theo dõi lớn. Xem https://stackoverflow.com/a/13631525/717372 để biết thêm chi tiết ...

git update-index --skip-worktree <file>

173
Đây câu trả lời thực sự. Tuyệt vời thực sự, rất đơn giản, không gây ô nhiễm git statusvà thực sự rất trực quan. Cảm ơn.
Pablo Olmos de Aguilera C.

4
Tôi đã đi cho rm [...] .giải pháp đủ tốt , vì ít nhất tôi có thể tự mò mẫm cách nó hoạt động. Tôi không tìm thấy tài liệu tuyệt vời về những gì update-index--assume-unchangedlàm. Bất cứ ai cũng có thể thêm làm thế nào cái này so sánh với cái kia, trong đó tôi muốn xóa tất cả các tệp sẽ bị bỏ qua? (Hoặc một liên kết để giải thích rõ ràng?)
Brady Trainor

25
git update-index --assume-unchanged <path> …sẽ khiến git bỏ qua các thay đổi trong (các) đường dẫn đã chỉ định, bất kể .gitignore. Nếu bạn kéo từ xa và điều khiển từ xa có thay đổi đối với đường dẫn này, git sẽ không hợp nhất với xung đột và bạn sẽ cần hợp nhất thủ công. git rm --cached <path> …sẽ khiến git ngừng theo dõi con đường đó. Nếu bạn không thêm đường dẫn vào, .gitignorebạn sẽ thấy đường dẫn trong tương lai git status. Tùy chọn đầu tiên có ít tiếng ồn hơn trong lịch sử cam kết git và cho phép thay đổi tệp "bị bỏ qua" sẽ được phân phối trong tương lai.
ManicDee

26
Tôi khá bối rối vì làm thế nào đây không phải là câu trả lời được chấp nhận. Câu trả lời được chấp nhận ở đây rõ ràng không trả lời câu hỏi thực tế đang được hỏi. Câu trả lời này bỏ qua các thay đổi đối với tệp trong kho lưu trữ trong khi không xóa tệp khỏi kho lưu trữ.
Dave Cooper

11
Câu trả lời này sẽ hữu ích hơn rất nhiều nếu nó giải thích chính xác những gì lệnh đã cho, ví dụ như nó khác với các giải pháp được đề xuất khác như thế nào.
LarsH

283
git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

Thao tác này sẽ lấy danh sách các tệp bị bỏ qua và xóa chúng khỏi chỉ mục, sau đó cam kết thay đổi.


7
Nếu bạn cũng cần xóa chúng khỏi thư mục làm việc, thì chỉ cần chạy git ls-files --ignored --exclude-standard | xargs git rm . Tôi tin rằng câu trả lời này là tốt nhất! Bởi vì nó rất rõ ràng, theo cách Unix và thực hiện điều mong muốn theo cách trực tiếp, mà không tạo ra các tác dụng phụ của các lệnh phức tạp hơn khác.
imz - Ivan Zakharyaschev 27/2/2015

6
Câu trả lời chính xác; tuy nhiên, lệnh sẽ thất bại nếu bạn có các đường dẫn có khoảng trắng ở giữa, ví dụ: "dir của tôi / my_ignored_file.txt"
David Hernandez

8
git ls-files --ignored --exclude-standard | sed 's /.*/"&"/' | xargs git rm - đã tham gia
David Hernandez

3
git rmsẽ khiếu nại nếu ls-fileskhông phù hợp với bất cứ điều gì. Sử dụng xargs -r git rm ...để báo xargskhông chạy git rmnếu không có tệp nào khớp.
Wolfgang

10
Sẽ tốt hơn nếu sử dụng \ 0 làm dấu phân cách:git ls-files --ignored --exclude-standard -z|xargs -0 git rm --cached
Nils-o-mat

83

Tôi luôn luôn sử dụng lệnh này để loại bỏ các tập tin không bị theo dõi. Một dòng, kiểu Unix, đầu ra sạch:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

Nó liệt kê tất cả các tệp bị bỏ qua của bạn, thay thế mọi dòng đầu ra bằng một dòng được trích dẫn thay vào đó để xử lý các đường dẫn có khoảng trắng bên trong và chuyển mọi thứ git rm -r --cachedđể xóa các đường dẫn / tệp / thư mục khỏi chỉ mục.


3
Giải pháp tuyệt vời! Hoạt động hoàn hảo và cảm thấy chính xác hơn khi xóa tất cả các tệp sau đó thêm chúng trở lại.
Jon Catmull

5
Tôi cũng tìm thấy "sạch nhất" này. Điều này có thể rõ ràng, nhưng chỉ cần chạy phần đầu tiên, git ls-files --ignored --exclude-standardtự nó cho phép bạn hiểu / xác minh những tập tin mới mà bạn .gitignoresẽ loại trừ / loại bỏ, trước khi bạn tiếp tục và thực hiện cuối cùng git rm.
JonBrave

Hãy nhận biết, thất bại trên tên tập tin với các nhân vật "khó chịu" nhất định trong đó, ví dụ \n. Tôi đã đăng giải pháp của tôi để phục vụ cho việc này.
JonBrave

3
Một cảnh báo khác: khi kéo, điều này sẽ khiến tập tin bị xóa trong thư mục làm việc của người khác, phải không?
LarsH

đã thử, nhưng không hiệu quả với tôi: sed: 1: "s/.*/": unterminated substitute in regular expressiontrong lệnh lọc nhánh trên repo có khoảng trắng. (Dường như hoạt động bên ngoài nhánh lọc). Tôi đã sử dụng git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cachedtừ câu trả lời của @ JonBrave thay thế.
goofology

71

di chuyển nó ra, cam kết, sau đó di chuyển nó trở lại. Điều này đã làm việc cho tôi trong quá khứ. Có lẽ có một cách 'gittier' để thực hiện điều này.


2
Điều này hoạt động rất tốt nếu bạn muốn bỏ qua một loạt các tệp mà trước đây không được bỏ qua. Mặc dù như bạn đã nói, có lẽ có một cách tốt hơn cho việc này.
Oskar Persson

Đây chính xác là những gì tôi đã làm. Chỉ cần di chuyển các tệp vào một thư mục bên ngoài git, sau đó thực hiện "git add.", "Git commit". (Điều này đã xóa các tệp) sau đó thêm gitignore, tham chiếu các tệp / thư mục, cam kết lại để thêm tệp gitignore vào git, sau đó sao chép / di chuyển trở lại trong các thư mục và chúng sẽ bị bỏ qua. Lưu ý: có vẻ như các tệp đã bị xóa khỏi GIT, do đó có thể sẽ xóa chúng khỏi các lần kiểm tra / kéo khác, như đã đề cập trong các giải pháp trên, nhưng vì ban đầu bạn đang tạo các bản sao của chúng, đây không phải là vấn đề IMHO. chỉ cần cho các thành viên còn lại biết ...
Del

Đây là cách dễ nhất để thoát khỏi các thư mục cam kết sai.
Martlark

2
Có vẻ là cách duy nhất, mà tôi có thể thấy. Đó là một lỗi lớn (không phải 'tính năng') trong git mà ngay khi bạn thêm tệp / thư mục vào .gitignore, nó sẽ không bỏ qua tệp đó từ thời điểm đó - mãi mãi - ở mọi nơi.
JosephK

Điều này hoạt động sau khi tôi đã thêm chúng, và sau đó thực tế đã thêm chúng vào .gitignore
hanzolo

66

Nếu bạn không thể git rmtheo dõi tệp vì người khác có thể cần nó (cảnh báo, ngay cả khi bạn git rm --cached , khi người khác nhận được thay đổi này, tệp của họ sẽ bị xóa trong hệ thống tệp của họ). Chúng thường được thực hiện do ghi đè tệp cấu hình, thông tin xác thực, v.v. Vui lòng xem https://gist.github.com/1423106 để biết cách mọi người giải quyết vấn đề.

Để tóm tắt:

  • Yêu cầu ứng dụng của bạn tìm tệp config-overide.ini bị bỏ qua và sử dụng tệp đó qua tệp config.ini (hoặc cách khác, tìm ~ / .config / myapp.ini hoặc $ MYCONFIGFILE)
  • Cam kết tập tin config-sample.ini và bỏ qua tập tin config.ini, có tập lệnh hoặc sao chép tập tin tương tự nếu cần thiết.
  • Cố gắng sử dụng ma thuật dọn dẹp / làm nhòe để áp dụng và xóa các thay đổi cho bạn, ví dụ, làm nhòe tệp cấu hình dưới dạng thanh toán từ một nhánh thay thế và làm sạch tệp cấu hình dưới dạng thanh toán từ HEAD. Đây là một thứ khó khăn, tôi không khuyên dùng nó cho người dùng mới làm quen.
  • Giữ tệp cấu hình trên một nhánh triển khai dành riêng cho nó không bao giờ được hợp nhất với chủ. Khi bạn muốn triển khai / biên dịch / kiểm tra, bạn hợp nhất với nhánh đó và lấy tệp đó. Đây thực chất là cách tiếp cận smudge / sạch ngoại trừ sử dụng các chính sách hợp nhất của con người và các mô-đun bổ sung.
  • Chống tái phát: Đừng sử dụng giả định, nó sẽ chỉ kết thúc trong nước mắt (bởi vì việc nói dối với chính nó sẽ khiến những điều tồi tệ xảy ra, như thay đổi của bạn bị mất mãi mãi).

7
git sẽ không xóa tập tin, nếu nó bị bẩn tại thời điểm xóa. Và nếu nó không bẩn, việc lấy tệp sẽ dễ dàng như git checkout <oldref> -- <filename>- nhưng sau đó nó sẽ được kiểm tra và bỏ qua.
amenthes

Liên quan đến ghi chú cuối cùng của bạn (về --assume-unchanged): đây là sự sùng bái hàng hóa và nên được loại bỏ, hoặc bạn có thể giải thích tại sao (mà tôi bị thuyết phục) và nó trở nên hữu ích.
RomainValeri

57

Sử dụng cái này khi:

1. Bạn muốn mở khóa nhiều tệp, hoặc

2. Bạn đã cập nhật tệp gitignore của bạn

Liên kết nguồn: http://www.codeblocq.com/2016/01/Untrack-files-alpered-added-to-git-reposeective-basing-on-gitignore/

Giả sử bạn đã thêm / cam kết một số tệp vào kho git của mình và sau đó bạn thêm chúng vào .gitignore; những tập tin này sẽ vẫn có mặt trong chỉ mục kho lưu trữ của bạn. Bài viết này chúng ta sẽ xem làm thế nào để thoát khỏi chúng.

Bước 1: Cam kết tất cả các thay đổi của bạn

Trước khi tiếp tục, hãy đảm bảo tất cả các thay đổi của bạn được cam kết, bao gồm cả tệp .gitignore của bạn.

Bước 2: Xóa mọi thứ khỏi kho lưu trữ

Để xóa repo của bạn, sử dụng:

git rm -r --cached .
  • rm là lệnh remove
  • -r sẽ cho phép loại bỏ đệ quy
  • Phần mềm sẽ chỉ xóa các tệp khỏi chỉ mục. Các tập tin của bạn sẽ vẫn ở đó.

Các rmlệnh có thể được tha thứ. Nếu bạn muốn thử những gì nó làm trước đó, hãy thêm -nhoặc --dry-rungắn cờ để kiểm tra mọi thứ.

Bước 3: Thêm lại mọi thứ

git add .

Bước 4: Cam kết

git commit -m ".gitignore fix"

Kho lưu trữ của bạn sạch sẽ :)

Đẩy các thay đổi vào điều khiển từ xa để xem các thay đổi có hiệu quả ở đó.


1
Nó sẽ không xóa các tập tin từ kho lưu trữ từ xa? Điều gì sẽ xảy ra nếu tôi muốn giữ các tệp cả trong repo cục bộ và repo từ xa nhưng làm cho git "quên" về chúng?
Avishay28

AFAIK điều này sẽ không xóa các tệp khỏi lịch sử vì chúng tôi không sử dụng bất kỳ lệnh thay đổi lịch sử nào (sửa tôi nếu tôi sai). Điều này chỉ thêm một cam kết mới bằng cách xóa các tệp bị bỏ qua trong gitignore khỏi git. Các tệp đó sẽ ở đó trong các cam kết lịch sử
Dheeraj Bhaskar

49

Tôi đã thực hiện điều này bằng cách sử dụng nhánh lọc git . Lệnh chính xác tôi đã sử dụng được lấy từ trang man:

CẢNH BÁO : việc này sẽ xóa tệp khỏi toàn bộ lịch sử của bạn

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

Lệnh này sẽ tạo lại toàn bộ lịch sử cam kết, thực thi git rmtrước mỗi lần xác nhận và do đó sẽ thoát khỏi tệp được chỉ định. Đừng quên sao lưu nó trước khi chạy lệnh vì nó sẽ bị mất.


9
Điều này sẽ thay đổi tất cả các ID cam kết, do đó phá vỡ các hợp nhất từ ​​các nhánh bên ngoài bản sao của kho lưu trữ của bạn.
bdonlan

19
CẢNH BÁO: việc này sẽ xóa tệp khỏi toàn bộ lịch sử của bạn. Đây là những gì tôi đang tìm kiếm, để loại bỏ một tệp hoàn toàn không cần thiết và quá khổ (đầu ra không bao giờ nên được cam kết) đã được cam kết từ lâu trong lịch sử phiên bản.
zebediah49

48

Điều gì đã không làm việc cho tôi

(Trong Linux), tôi muốn sử dụng các bài đăng ở đây gợi ý ls-files --ignored --exclude-standard | xargs git rm -r --cachedcách tiếp cận. Tuy nhiên, (một số) các tệp cần xóa có một dòng mới được nhúng / LF / \ntrong tên của chúng. Cả hai giải pháp:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

đối phó với tình huống này (nhận lỗi về các tập tin không được tìm thấy).

Vì vậy, tôi cung cấp

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

Điều này sử dụng -zđối số cho các tệp ls-0đối số cho xargs để phục vụ an toàn / chính xác cho các ký tự "khó chịu" trong tên tệp.

Trong trang hướng dẫn git-ls-files (1) , nó ghi:

Khi tùy chọn -z không được sử dụng, các ký tự TAB, LF và dấu gạch chéo ngược trong tên đường dẫn được biểu diễn lần lượt là \ t, \ n và \\.

Vì vậy, tôi nghĩ rằng giải pháp của tôi là cần thiết nếu tên tập tin có bất kỳ nhân vật nào trong đó.


1
Đối với tôi đây là giải pháp tốt nhất. Nó có hiệu suất tốt hơn nhiều so với a git add .. Nó cũng chứa những cải tiến tốt nhất từ ​​một số ý kiến ​​trên.
Nils-o-mat

Bạn có thể thêm git commit -am "Remove ignored files"câu trả lời của thSoft vào câu trả lời của bạn không? Câu trả lời của bạn kết hợp đã đưa tôi qua mọi thứ: j
kando

Tôi không hiểu mục đích của git commit -a. Đối với tôi git rm --cachedảnh hưởng chính xác đến chỉ mục nên không cần phải xử lý các tệp sau ...
Jean Paul

23
  1. Cập nhật .gitignoretệp của bạn - ví dụ: thêm thư mục bạn không muốn theo dõi .gitignore.

  2. git rm -r --cached .- Xóa tất cả các tập tin được theo dõi, bao gồm muốn và không mong muốn. Mã của bạn sẽ được an toàn miễn là bạn đã lưu cục bộ.

  3. git add .- Tất cả các tệp sẽ được thêm lại, ngoại trừ những tệp trong .gitignore.


Hat tip cho @AkiraYamamoto vì đã chỉ cho chúng tôi đi đúng hướng.


1
Làm thế nào về việc bị hạ cấp do thực tế là nó sẽ không thực sự hoạt động vì bạn cần một -r để chạy rm đệ quy bằng mọi cách :) (Ai đó đã không sao chép chính xác)
Aran Mulholland

1
Cảnh báo: Kỹ thuật này không thực sự khiến git bỏ qua tệp, thay vào đó nó thực sự khiến git xóa tệp. Điều đó có nghĩa là nếu bạn sử dụng giải pháp này, bất cứ khi nào bất kỳ ai khác thực hiện thao tác git, tệp sẽ bị xóa. Vì vậy, nó không thực sự bị bỏ qua. Xem giải pháp đề xuất chỉ số cập nhật git - thay đổi không thay đổi để biết giải pháp cho câu hỏi ban đầu.
orrd

16

Tôi nghĩ rằng, có lẽ git hoàn toàn không thể quên tập tin vì quan niệm của nó ( phần "Ảnh chụp nhanh, không khác biệt" ).

Vấn đề này vắng mặt, ví dụ, khi sử dụng CVS. CVS lưu trữ thông tin dưới dạng danh sách các thay đổi dựa trên tệp. Thông tin cho CVS là một tập hợp các tệp và các thay đổi được thực hiện cho từng tệp theo thời gian.

Nhưng trong Git mỗi khi bạn cam kết hoặc lưu trạng thái của dự án, về cơ bản, nó sẽ chụp ảnh tất cả các tệp của bạn trông như thế nào vào thời điểm đó và lưu trữ một tham chiếu đến ảnh chụp nhanh đó. Vì vậy, nếu bạn đã thêm tệp một lần, nó sẽ luôn có mặt trong ảnh chụp nhanh đó.

2 bài viết này rất hữu ích cho tôi:

git giả-không thay đổi so với Skip-worktree Cách bỏ qua các thay đổi trong các tệp được theo dõi bằng Git

Dựa vào đó tôi làm như sau, nếu tập tin đã được theo dõi:

git update-index --skip-worktree <file>

Từ thời điểm này, tất cả các thay đổi cục bộ trong tệp này sẽ bị bỏ qua và sẽ không chuyển sang điều khiển từ xa. Nếu tập tin được thay đổi trên remote, xung đột sẽ xảy ra, khi nào git pull. Stash sẽ không hoạt động. Để giải quyết nó, sao chép nội dung tệp vào nơi an toàn và làm theo các bước sau:

git update-index --no-skip-worktree <file>
git stash
git pull 

Nội dung tập tin sẽ được thay thế bởi nội dung từ xa. Dán các thay đổi của bạn từ nơi an toàn vào tệp và thực hiện lại:

git update-index --skip-worktree <file>

Nếu tất cả mọi người, những người làm việc với dự án, sẽ thực hiện git update-index --skip-worktree <file>, không có vấn đề gì pull. Giải pháp này phù hợp với các tệp cấu hình, khi mọi nhà phát triển có cấu hình dự án riêng.

Nó không phải là rất thuận tiện để làm điều này mỗi lần, khi tập tin đã được thay đổi trên điều khiển từ xa, nhưng có thể bảo vệ nó khỏi bị ghi đè bởi nội dung từ xa.


16

Thực hiện các bước sau đây, bạn sẽ ổn thôi.

1. loại bỏ các tập tin thêm nhầm từ thư mục / lưu trữ . Bạn có thể sử dụng lệnh "rm -r" (cho linux) hoặc xóa chúng bằng cách duyệt các thư mục. Hoặc di chuyển chúng đến một vị trí khác trên PC của bạn. [Bạn có thể cần phải đóng IDE nếu đang chạy để di chuyển / gỡ bỏ ]

2. thêm các tập tin / thư mục vào gitignore tập tin bây giờ và lưu nó.

3.now xóa chúng khỏi git cache bằng cách sử dụng các lệnh này (nếu có nhiều hơn một thư mục, hãy xóa từng cái một bằng cách liên tục ban hành lệnh này)

git rm -r --cached path-to-those-files

4.now thực hiện một cam kết và đẩy , sử dụng các lệnh này. Thao tác này sẽ xóa các tệp đó khỏi git từ xa và khiến git dừng theo dõi các tệp đó.

git add .
git commit -m "removed unnecessary files from git"
git push origin

13

Câu trả lời sao chép / dán là git rm --cached -r .; git add .; git status

Lệnh này sẽ bỏ qua các tệp đã được cam kết với kho Git nhưng bây giờ chúng tôi đã thêm chúng vào .gitignore.


9

Câu trả lời từ Matt Fear là IMHO hiệu quả nhất. Dưới đây chỉ là tập lệnh PowerShell cho những người trong windows để chỉ xóa các tệp khỏi repo git của họ phù hợp với danh sách loại trừ của họ.

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git 
$ignoreFiles | % { git rm $_}

git add .

Trong tình huống nào danh sách các tệp này sẽ bằng với đệ quy --cached?
John Zabroski

8

Di chuyển hoặc sao chép tệp vào một vị trí an toàn để bạn không bị mất. Sau đó git rm các tập tin và cam kết. Tệp sẽ vẫn hiển thị nếu bạn hoàn nguyên về một trong những cam kết trước đó hoặc một nhánh khác nơi nó chưa bị xóa. Tuy nhiên, trong tất cả các cam kết trong tương lai, bạn sẽ không thấy tệp đó nữa. Nếu tệp nằm trong git bỏ qua, thì bạn có thể di chuyển nó trở lại vào thư mục và git sẽ không thấy nó.


34
git rm --cachedsẽ xóa tệp khỏi chỉ mục mà không xóa tệp khỏi đĩa, do đó không cần phải di chuyển / sao chép tệp đi
bdonlan

7

Sử dụng git rm --cachedlệnh không trả lời câu hỏi ban đầu:

Làm thế nào để bạn buộc gitphải hoàn toàn quên về [một tập tin]?

Trong thực tế, giải pháp này sẽ khiến tệp bị xóa trong mọi phiên bản khác của kho lưu trữ khi thực hiện mộtgit pull !

Cách chính xác để buộc git quên một tệp được ghi lại bởi GitHub tại đây .

Tôi khuyên bạn nên đọc tài liệu, nhưng về cơ bản:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
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

chỉ cần thay thế full/path/to/filebằng đường dẫn đầy đủ của tập tin. Hãy chắc chắn rằng bạn đã thêm tệp vào.gitignore .

Bạn cũng cần (tạm thời) cho phép các lần đẩy không nhanh về kho lưu trữ của mình , vì bạn đang thay đổi lịch sử git của mình.


5

Các BFG được thiết kế đặc biệt để loại bỏ dữ liệu không mong muốn như các tập tin lớn hoặc mật khẩu từ Repos Git, vì vậy nó có một lá cờ đơn giản mà sẽ loại bỏ bất kỳ lịch sử lớn (không-trong-bạn-hiện tại-cam) tập tin: '--strip-blobs- to hơn'

$ java -jar bfg.jar --strip-blobs-bigger-than 100M

Nếu bạn muốn chỉ định tệp theo tên, bạn cũng có thể làm điều đó:

$ java -jar bfg.jar --delete-files *.mp4

BFG nhanh hơn 10-1000 lần so với nhánh bộ lọc git và thường dễ sử dụng hơn nhiều - kiểm tra hướng dẫn sử dụng đầy đủví dụ để biết thêm chi tiết.

Nguồn: https://confluence.atlassian.com/bitbucket/reduce-reposeective-size-321848262.html


5

Nếu bạn không muốn sử dụng CLI và đang làm việc trên Windows, một giải pháp rất đơn giản là sử dụng TortoiseGit , nó có Hành động "Xóa (giữ cục bộ)" trong menu hoạt động tốt.


5

Tôi thích câu trả lời của JonBrave nhưng tôi có những thư mục làm việc đủ lộn xộn mà cam kết - tôi sợ tôi một chút, vì vậy đây là những gì tôi đã làm:

git config --global alias.exclude-bị bỏ qua '! git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 giai đoạn git && giai đoạn git .gitignore && git commit -m "gitignore mới và xóa các tệp bị bỏ qua khỏi chỉ mục" '

phá vỡ nó:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached 
git ls-files -z --ignored --exclude-standard | xargs -0 git stage 
git stage .gitignore 
git commit -m "new gitignore and remove ignored files from index"
  • xóa các tập tin bị bỏ qua khỏi chỉ mục
  • giai đoạn .gitignore và các tệp bạn vừa xóa
  • cam kết

4

Đây không còn là một vấn đề trong git mới nhất (v2.17.1 tại thời điểm viết bài).

Các .gitignorecuối cùng bỏ qua theo dõi-nhưng-xóa các tập tin. Bạn có thể tự kiểm tra điều này bằng cách chạy đoạn script sau. git statusTuyên bố cuối cùng sẽ báo cáo "không có gì để cam kết".

# Create empty repo
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status

Tôi rất vui vì git bây giờ làm điều này. Tuy nhiên, OP đã hỏi về việc không theo dõi các sửa đổi trong các tệp có trong .gitignore, các tệp không bị xóa vẫn hiển thị trạng thái.
mrturtle

2

Trong trường hợp đã cam kết DS_Store:

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

Bỏ qua chúng bằng cách:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

Cuối cùng, thực hiện một cam kết!


2

Đặc biệt đối với các tệp dựa trên IDE, tôi sử dụng:

Ví dụ, slnx.sqlite, tôi đã loại bỏ nó hoàn toàn như sau:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

Chỉ cần lưu ý rằng một số tệp đó lưu trữ một số cài đặt và tùy chọn người dùng cục bộ cho các dự án (như những tệp bạn đã mở). Vì vậy, mỗi khi bạn điều hướng hoặc thực hiện một số thay đổi trong IDE của mình, tệp đó sẽ được thay đổi và do đó nó sẽ kiểm tra và hiển thị khi có những thay đổi không được cam kết.


2

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/.git/info/excludecó 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 .gitignoretệ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 .gitignoretrong 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/excludecó thể hoàn thành điều tương tự bất kể nơi .gitignorenà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 rebasehoặc một git filter-branchbả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 --cachedlệ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-emptycờ trong những điều sau git filter-branchlệ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 .


0

Nếu bất cứ ai gặp khó khăn trên Windows và bạn muốn bỏ qua toàn bộ thư mục, 'cd' để mong muốn 'thư mục' và thực hiện 'Git Bash Here'.

git ls-files -z | xargs -0 git update-index --assume-unchanged

0

Trong trường hợp của tôi ở đây, tôi đã có một số tệp .lock trong một số thư mục mà tôi cần phải xóa. Tôi đã chạy như sau và nó hoạt động mà không cần phải đi vào từng thư mục để loại bỏ chúng:

git rm -r --cached **/*.lock

Làm điều này đã đi vào từng thư mục dưới 'root' nơi tôi đang ở và loại trừ tất cả các tệp khớp với mẫu.

Hy vọng điều này sẽ giúp người khác!

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.