Làm cách nào để loại bỏ số lượng lớn tệp mà không xóa nội dung


454

Tôi vô tình thêm rất nhiều tập tin tạm thời bằng cách sử dụng git add -A

Tôi đã quản lý để loại bỏ các tập tin bằng cách sử dụng các lệnh sau và quản lý để loại bỏ chỉ mục bẩn.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Các lệnh trên được liệt kê trong git help rm. Nhưng thật đáng buồn, các tập tin của tôi cũng bị xóa khi thực thi, mặc dù tôi đã đưa ra tùy chọn bộ đệm. Làm thế nào tôi có thể xóa chỉ mục mà không mất nội dung?

Ngoài ra nó sẽ hữu ích nếu ai đó có thể giải thích cách hoạt động của đường ống này.


8
rm -fkhông phải là lệnh git và không có --cachedtùy chọn. Các tệp cục bộ của bạn đã bị xóa trước khi bạn thực thi git rmvì vậy tôi không nghĩ rằng bạn có thể đổ lỗi một cách hợp pháp git rmcho bất cứ điều gì.
CB Bailey

8
@sarat, vui lòng xem xét việc thay đổi câu trả lời chính xác cho câu trả lời được đánh giá cao từ Ian Maddox , vì git reset --hardđây không phải là câu trả lời đúng và trên thực tế sẽ xóa nội dung. Điều này sẽ gây nhầm lẫn cho người dùng - như nó đã làm tôi.
Marco Pashkov

2
@sarat như Marco nói, cứ tiếp tục. Trang này nhận được rất nhiều lưu lượng truy cập.
Ross

@MarcoPashkov & Ross cảm ơn các bạn. Làm xong.
sarat 30/03/2015

Câu trả lời:


986

git reset

Nếu tất cả những gì bạn muốn là hoàn tác một "git add" quá nhiệt tình:

git reset

Những thay đổi của bạn sẽ không được thực hiện và sẵn sàng để bạn thêm lại khi bạn muốn.


KHÔNG CHẠY git reset --hard.

Nó sẽ không chỉ bỏ qua các tập tin đã thêm của bạn, mà sẽ hoàn nguyên mọi thay đổi bạn đã thực hiện trong thư mục làm việc của mình. Nếu bạn đã tạo bất kỳ tệp mới trong thư mục làm việc, nó sẽ không xóa chúng.


15
Tôi nợ bạn một pint Ian
DasBooten

1
Tôi thường tìm tôi phải thực hiện git checkout -- *cũng
Den-Jason

1
Bạn đã tiết kiệm rất nhiều nỗ lực. Cảm ơn người đàn ông
RajnikantDixit

35

Nếu bạn có một repo nguyên sơ (hoặc HEAD không được đặt) [1] bạn có thể chỉ cần

rm .git/index

Tất nhiên, điều này sẽ yêu cầu bạn phải thêm lại các tập tin mà bạn đã muốn được thêm vào.


[1] Lưu ý (như được giải thích trong các bình luận) điều này thường chỉ xảy ra khi repo hoàn toàn mới ("nguyên sơ") hoặc nếu không có cam kết nào được thực hiện. Kỹ thuật hơn, bất cứ khi nào không có thanh toán hoặc cây làm việc.

Chỉ cần làm cho nó rõ ràng hơn :)


Phải, nó giống như xóa chính chỉ mục đã tạo. Điều tốt là, tôi không yêu cầu khởi tạo lại git. Cảm ơn!
sarat

Có chắc chắn đó là một hoạt động an toàn? Tôi chỉ làm điều này (thực sự di chuyển chỉ mục ra khỏi đường đi) và có tất cả các tệp khác được dàn dựng để xóa.
inger

@inger "Nếu bạn có một repo nguyên sơ". Bạn rõ ràng không có điều đó.
sehe

Trên thực tế, tôi đã tự hỏi ý của bạn là "repo nguyên sơ" (tôi cũng không cảm thấy may mắn với google) .. Vậy ý bạn thực sự là một repo trống?
inger

1
@inger Đồng ý. Tôi đã phải giả định rằng OP đã tình cờ có tình huống chính xác này - anh ta không chỉ định nó, nhưng mô tả của anh ta để lại khả năng. Dù sao, tôi chỉ đang chia sẻ thông tin và không thể ảnh hưởng đến việc bỏ phiếu :(. Đã thêm một lời cảnh báo vào văn bản trả lời, trong trường hợp nó giúp người khác trong tương lai.
sehe

15

Sử dụng git reset HEADđể thiết lập lại chỉ mục mà không loại bỏ các tập tin. (Nếu bạn chỉ muốn đặt lại một tệp cụ thể trong chỉ mục, bạn có thể sử dụng git reset HEAD -- /path/to/fileđể làm như vậy.)

Toán tử đường ống, trong một vỏ, lấy stdoutquy trình ở bên trái và chuyển nó stdinsang quy trình ở bên phải. Về cơ bản , nó tương đương với:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

nhưng thay vào đó $ proc1 | proc2, quy trình thứ hai có thể bắt đầu nhận dữ liệu trước khi quá trình đầu tiên được thực hiện và không có tệp thực sự nào liên quan.


nhưng làm thế nào để sử dụng nó với nhiều tập tin. Tôi chưa bao giờ cam kết những tập tin này trước đây.
sarat

3
Chỉ cần gõ git reset HEADmà không chỉ định bất cứ điều gì khác, và nó sẽ thiết lập lại toàn bộ chỉ mục. Sau đó, bạn chỉ có thể thêm lại các tệp bạn muốn.
Amber

Tôi đã nhận được lỗi sau. Tôi chưa bao giờ cam kết những mục này trước đây. $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
sarat

1
Hãy thử ngay git resetsau đó, mà không có HEAD.
Amber

Tôi đã cố gắng rằng tôi đã kết thúc trong lỗi sau. $ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
sarat

9
git stash && git stash pop

2
Tôi sẽ thực hiện 'git stash && git stash pop' để stash cũng bị xóa. 'áp dụng' sẽ để lại stash trong danh sách stash.
chitti

8

Nếu HEAD chưa được đặt (nghĩa là bạn chưa có cam kết, nhưng bạn không muốn thổi bay đi .gitvì bạn đã thiết lập cấu hình repo khác mà bạn muốn giữ), bạn cũng có thể làm

git rm -rf --cached .

để giải phóng mọi thứ. Điều này thực sự giống như giải pháp của sehe, nhưng tránh làm phiền với nội bộ Git.


điều này thực sự bảo Git xóa mọi thứ trong vùng được lưu trữ.
Giải pháp phần mềm có tầm nhìn

1
Bộ nhớ cache còn được gọi là khu vực tổ chức, vì vậy tôi không chắc bạn đang làm gì.
jjlin

Từ sehe, rm .git / index rất nguy hiểm - hãy chắc chắn đọc LƯU Ý anh ấy có về một repo hoàn toàn mới! Điều này an toàn hơn nhiều cho 99,999% còn lại. Tôi đã không đọc kỹ và phải thổi bay bản sao làm việc của mình và sao chép lại sau khi thực hiện rm .git / index trên bản sao làm việc của mình.
phpguru

KHÔNG sử dụng lệnh này! Nó sẽ thay đổi TẤT CẢ dự án sang trạng thái không bị theo dõi (bao gồm cả những dự án không được dàn dựng). Đây không phải là một giải pháp cho câu hỏi ban đầu. Giải pháp chính xác bằng cách sử dụng lệnh 'git rm' là CHỈ chỉ định các tệp bạn muốn không được phân loại: git rm -rf --cached <các tệp bạn muốn hủy kích hoạt>.
Monte Creasor

Bạn chỉ nên sử dụng lệnh này khi bạn có một repo mới chưa có xác nhận (đây là ý nghĩa của "ĐẦU KHÔNG được đặt"), nhưng bạn không muốn thổi bay đi .gitvì bạn đã thiết lập cấu hình repo khác cho bạn muốn giữ lấy. Tôi đã chỉnh sửa để làm rõ điều này.
jjlin

5

Cảnh báo: không sử dụng lệnh sau trừ khi bạn muốn mất công việc không được cam kết!

Việc sử dụng git resetđã được giải thích, nhưng bạn cũng đã yêu cầu một lời giải thích về các lệnh đường ống, vì vậy ở đây đi:

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Lệnh git ls-filesliệt kê tất cả các tập tin git biết về. Tùy chọn -záp đặt một định dạng cụ thể cho chúng, định dạng được mong đợi xargs -0, sau đó gọi rm -fchúng, có nghĩa là loại bỏ chúng mà không cần kiểm tra sự chấp thuận của bạn.

Nói cách khác, "liệt kê tất cả các tệp git biết và xóa bản sao cục bộ của bạn".

Sau đó, chúng tôi nhận được git diff, cho thấy những thay đổi giữa các phiên bản khác nhau của vật phẩm mà git biết. Đó có thể là những thay đổi giữa các cây khác nhau, sự khác biệt giữa các bản sao địa phương và bản sao từ xa, v.v.
Như được sử dụng ở đây, nó cho thấy những thay đổi chưa được thực hiện; các tập tin bạn đã thay đổi nhưng chưa cam kết. Tùy chọn này --name-onlycó nghĩa là bạn chỉ muốn tên tệp (đầy đủ) và --diff-filter=Dcó nghĩa là bạn chỉ quan tâm đến các tệp bị xóa. (Này, không phải chúng ta đã xóa một loạt các thứ sao?) Cái này sau đó được dẫn vào cái xargs -0mà chúng ta đã thấy trước đó, nó gọi git rm --cachedchúng, có nghĩa là chúng bị xóa khỏi bộ đệm, trong khi cây làm việc nên được để yên - ngoại trừ việc bạn vừa xóa tất cả các tệp khỏi cây làm việc của bạn. Bây giờ họ cũng bị xóa khỏi chỉ mục của bạn.

Nói cách khác, tất cả các thay đổi, dàn dựng hoặc không được dàn dựng đều biến mất và cây làm việc của bạn trống rỗng. Hãy khóc, kiểm tra các tập tin của bạn mới từ nguồn gốc hoặc từ xa, và làm lại công việc của bạn. Nguyền rủa kẻ tàn bạo đã viết những dòng vô sinh này; Tôi không có manh mối nào tại sao mọi người muốn làm điều này.


TL; DR: bạn vừa hos mọi thứ; bắt đầu lại và sử dụng git resettừ bây giờ


2

Tôi sợ rằng dòng lệnh đầu tiên bị xóa vô điều kiện khỏi bản sao làm việc tất cả các tệp nằm trong khu vực tổ chức của git. Cái thứ hai chưa được xử lý tất cả các tệp đã được theo dõi nhưng hiện đã bị xóa. Thật không may, điều này có nghĩa là bạn sẽ mất bất kỳ sửa đổi không được cam kết nào đối với các tệp đó.

Nếu bạn muốn lấy bản sao làm việc của mình và lập chỉ mục về trạng thái của chúng ở lần xác nhận cuối cùng , bạn có thể ( cẩn thận ) sử dụng lệnh sau:

git reset --hard

Tôi nói "cẩn thận" vì git reset --hard sẽ xóa sạch những thay đổi không được cam kết trong bản sao và chỉ mục làm việc của bạn . Tuy nhiên, trong tình huống này có vẻ như bạn chỉ muốn quay lại trạng thái ở lần cam kết cuối cùng của mình và những thay đổi không được cam kết đã bị mất.

Cập nhật: có vẻ như từ nhận xét của bạn về câu trả lời của Amber rằng bạn chưa tạo ra bất kỳ cam kết nào (vì không thể giải quyết được vấn đề này), vì vậy điều này sẽ không giúp ích, tôi sợ.

Về cách các ống đó hoạt động: git ls-files -zgit diff --name-only --diff-filter=D -zcả hai đều đưa ra một danh sách các tên tệp được phân tách bằng byte 0. (Điều này rất hữu ích, vì, không giống như dòng mới, 0byte được đảm bảo không xuất hiện trong tên tệp trên các hệ thống giống Unix.) Chương trình xargsvề cơ bản xây dựng các dòng lệnh từ đầu vào tiêu chuẩn của nó, theo mặc định bằng cách lấy các dòng từ đầu vào tiêu chuẩn và thêm chúng vào cuối của dòng lệnh. Các -0tùy chọn nói để mong đợi đầu vào tiêu chuẩn để được phân cách bằng 0byte. xargscó thể gọi lệnh nhiều lần để sử dụng hết tất cả các tham số từ đầu vào tiêu chuẩn, đảm bảo rằng dòng lệnh không bao giờ trở nên quá dài.

Ví dụ đơn giản, nếu bạn có một tệp được gọi test.txt, với các nội dung sau:

hello
goodbye
hello again

... sau đó lệnh xargs echo whatever < test.txtsẽ gọi lệnh:

echo whatever hello goodbye hello again

Tôi chưa bao giờ thực hiện bất kỳ cam kết nào vì vậy nó sẽ nói như không thể giải quyết CHÍNH. Những gì chúng ta làm trong những tình huống như vậy. Cảm ơn rất nhiều vì đã giải thích chi tiết về đường ống.
sarat

8
Nếu bạn vừa thay đổi git của bạn bỏ qua và đã thêm git - hãy bao gồm rất nhiều tệp, KHÔNG chạy git reset - hãy bỏ qua chúng. HỌ S DEL ĐƯỢC XÓA !!
Ajoy

5
Uwaaahh !! Có lẽ bạn cần làm nổi bật từ "cẩn thận" . Tôi chỉ thấy ba từ "git reset --hard" và tất cả các tập tin chưa được chỉnh sửa của tôi là ... fufff !! Không còn!!!!!
Vineeth Chitteti

1

Nếu bạn muốn hủy bỏ tất cả các thay đổi, hãy sử dụng lệnh bên dưới,

git reset --soft HEAD

Trong trường hợp bạn muốn hủy bỏ thay đổi và hoàn nguyên chúng từ thư mục làm việc,

git reset --hard HEAD
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.