Ngoài ra câu trả lời được chấp nhận, nếu tệp được thêm nhầm của bạn là rất lớn, bạn có thể sẽ nhận thấy rằng, ngay cả sau khi xóa nó khỏi chỉ mục bằng ' git reset
', nó dường như vẫn chiếm không gian trong .git
thư mục.
Điều này không có gì phải lo lắng; tập tin thực sự vẫn còn trong kho lưu trữ, nhưng chỉ là một "đối tượng lỏng lẻo". Nó sẽ không được sao chép vào các kho lưu trữ khác (thông qua bản sao, đẩy) và không gian cuối cùng sẽ được thu hồi - mặc dù có lẽ không sớm. Nếu bạn lo lắng, bạn có thể chạy:
git gc --prune=now
Cập nhật (những gì tiếp theo là nỗ lực của tôi để xóa một số nhầm lẫn có thể phát sinh từ các câu trả lời được đánh giá cao nhất):
Vì vậy, đó là hoàn tác thực sự của git add
?
git reset HEAD <file>
?
hoặc là
git rm --cached <file>
?
Nói đúng ra, và nếu tôi không nhầm: không có .
git add
không thể hoàn tác - nói chung, an toàn.
Trước tiên hãy nhớ lại những gì git add <file>
thực sự làm:
Nếu <file>
đã không được theo dõi trước đó , git add
thêm nó vào bộ nhớ cache , với nội dung hiện tại của nó.
Nếu <file>
đã được theo dõi , hãy git add
lưu nội dung hiện tại (ảnh chụp nhanh, phiên bản) vào bộ đệm. Trong Git, hành động này vẫn được gọi là add , (không chỉ cập nhật nó), bởi vì hai phiên bản khác nhau (ảnh chụp nhanh) của một tệp được coi là hai mục khác nhau: do đó, cuối cùng chúng tôi thực sự thêm một mục mới vào bộ đệm cam kết sau.
Trước vấn đề này, câu hỏi hơi mơ hồ:
Tôi đã thêm nhầm tệp bằng cách sử dụng lệnh ...
Kịch bản của OP dường như là kịch bản đầu tiên (tệp không bị theo dõi), chúng tôi muốn "hoàn tác" để xóa tệp (không chỉ nội dung hiện tại) khỏi các mục được theo dõi. Nếu đây là trường hợp, thì nó ổn để chạy git rm --cached <file>
.
Và chúng tôi cũng có thể chạy git reset HEAD <file>
. Điều này nói chung là tốt hơn, bởi vì nó hoạt động trong cả hai trường hợp: nó cũng hoàn tác khi chúng tôi thêm sai một phiên bản của một mục đã được theo dõi.
Nhưng có hai hãy cẩn thận.
Thứ nhất: Có (như đã chỉ ra trong câu trả lời) chỉ có một kịch bản git reset HEAD
không hoạt động, nhưng git rm --cached
thực hiện: một kho lưu trữ mới (không có cam kết). Nhưng, thực sự, đây là một trường hợp thực tế không liên quan.
Thứ hai: Lưu ý rằng git reset HEAD
không thể phục hồi một cách kỳ diệu các nội dung tệp được lưu trong bộ nhớ cache trước đó, nó chỉ đồng bộ lại nó từ ĐẦU. Nếu chúng tôi viết sai git add
ghi đè lên một phiên bản không được cam kết trước đó, chúng tôi không thể khôi phục nó. Đó là lý do tại sao, nói đúng ra, chúng ta không thể hoàn tác [*].
Thí dụ:
$ git init
$ echo "version 1" > file.txt
$ git add file.txt # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add file.txt # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff file.txt
-version 2
+version 3
$ git add file.txt # Oops we didn't mean this
$ git reset HEAD file.txt # Undo?
$ git diff --cached file.txt # No dif, of course. stage == HEAD
$ git diff file.txt # We have irrevocably lost "version 2"
-version 1
+version 3
Tất nhiên, điều này không quan trọng lắm nếu chúng ta chỉ tuân theo quy trình làm việc lười biếng thông thường là chỉ thực hiện 'git add' để thêm tệp mới (trường hợp 1) và chúng tôi cập nhật nội dung mới thông qua git commit -a
lệnh , cam kết .
* (Chỉnh sửa: thực tế ở trên là chính xác, nhưng vẫn có thể có một số cách hơi bị hack / phức tạp để khôi phục các thay đổi đã được dàn dựng, nhưng không được cam kết và sau đó được ghi đè - xem các nhận xét của Johannes Matokic và iolsmit)
HEAD
hoặchead
có thể sử dụng@
thay choHEAD
thay thế. Xem câu trả lời này (phần cuối) để tìm hiểu lý do tại sao bạn có thể làm điều đó.