Làm cách nào để hoàn tác 'git add' trước khi xác nhận?


8964

Tôi đã thêm nhầm tệp vào Git bằng lệnh:

git add myfile.txt

Tôi chưa chạy git commit. Có cách nào để hoàn tác việc này không, vì vậy những tệp này sẽ không được đưa vào cam kết?


22
Bắt đầu với Git v1.8.4, tất cả các câu trả lời dưới đây sử dụng đó HEADhoặc headcó thể sử dụng @thay cho HEADthay 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 đó.

3
Tôi đã thực hiện một bản tóm tắt nhỏ trong đó hiển thị tất cả các cách để tạo ra một tập tin: stackoverflow.com/questions/6919121/ mẹo
Daniel Alder

5
Tại sao không kiểm tra git?
Erik Reppen

13
@ErikReppen git checkoutkhông xóa các thay đổi theo giai đoạn khỏi chỉ mục cam kết. Nó chỉ hoàn nguyên các thay đổi chưa được phân loại cho lần sửa đổi đã cam kết cuối cùng - mà nhân tiện cũng không phải là điều tôi muốn, tôi muốn những thay đổi đó, tôi chỉ muốn chúng trong lần cam kết sau.
paxos1977

4
Nếu bạn sử dụng Eclipse, đơn giản như việc bỏ chọn các tệp trong hộp thoại cam kết
Hamzahfrq

Câu trả lời:


10372

Bạn có thể hoàn tác git addtrước khi cam kết với

git reset <file>

sẽ loại bỏ nó khỏi chỉ mục hiện tại (danh sách "sắp được cam kết") mà không thay đổi bất cứ điều gì khác.

Bạn có thể dùng

git reset

không có bất kỳ tên tập tin nào để bỏ qua tất cả các thay đổi do. Điều này có thể có ích khi có quá nhiều tệp được liệt kê từng cái một trong một khoảng thời gian hợp lý.

Trong các phiên bản cũ của Git, các lệnh trên tương đương git reset HEAD <file>git reset HEADtương ứng, và sẽ thất bại nếu không HEADđược xác định (vì bạn chưa thực hiện bất kỳ cam kết nào trong kho lưu trữ của mình) hoặc mơ hồ (vì bạn đã tạo một nhánh được gọi HEAD, đó là một điều ngu ngốc mà bạn không nên làm). Tuy nhiên, điều này đã được thay đổi trong Git 1.8.2 , vì vậy, trong các phiên bản Git hiện đại, bạn có thể sử dụng các lệnh trên ngay cả trước khi thực hiện cam kết đầu tiên của mình:

"git reset" (không có tùy chọn hoặc tham số) được sử dụng để báo lỗi khi bạn không có bất kỳ cam kết nào trong lịch sử của mình, nhưng giờ đây nó cung cấp cho bạn một chỉ mục trống (để khớp với cam kết không tồn tại mà bạn thậm chí không bật).


92
Tất nhiên, đây không phải là một bản hoàn tác thực sự, bởi vì nếu git addghi đè sai một phiên bản không được dàn dựng trước đó, chúng tôi không thể khôi phục nó. Tôi đã cố gắng làm rõ điều này trong câu trả lời của tôi dưới đây.
leonbloy

7
git reset HEAD *.extnơi extlà các tập tin của phần mở rộng cho bạn muốn unadd. Đối với tôi đó là *.bmp&*.zip
boulder_ruby

18
@Jonny, chỉ mục (còn gọi là khu vực tổ chức) chứa tất cả các tệp, không chỉ các tệp đã thay đổi. Nó "bắt đầu cuộc sống" (khi bạn kiểm tra một cam kết hoặc sao chép một repo) như là một bản sao của tất cả các tệp trong cam kết được chỉ ra bởi HEAD. Vì vậy, nếu bạn xóa một tệp khỏi chỉ mục ( git rm --cached), điều đó có nghĩa là bạn đang chuẩn bị thực hiện một cam kết xóa tệp đó. git reset HEAD <filename>mặt khác sẽ sao chép tệp từ CHÍNH vào chỉ mục để cam kết tiếp theo sẽ không hiển thị bất kỳ thay đổi nào được thực hiện đối với tệp đó.
tự đại diện

11
Tôi chỉ phát hiện ra rằng có một git reset -pgiống như git add -p. Điều này thật tuyệt!
donquixote

10
Bạn thực sự có thể khôi phục ghi đè lên các thay đổi được dàn dựng trước đó nhưng không được cam kết nhưng không theo cách thân thiện và không an toàn 100% (ít nhất là tôi không tìm thấy): goto .git / object, tìm kiếm các tệp được tạo tại thời điểm git addbạn muốn khôi phục ( 61/3AF3...- > id đối tượng 613AF3...), sau đó git cat-file -p <object-id>(có thể đáng để phục hồi vài giờ làm việc nhưng cũng là bài học để cam kết thường xuyên hơn ...)
Peter Schneider

2151

Bạn muốn:

git rm --cached <added_file_to_undo>

Lý do:

Khi tôi mới làm điều này, lần đầu tiên tôi đã thử

git reset .

(để hoàn tác toàn bộ tiện ích ban đầu của tôi), chỉ để nhận được thông báo hữu ích này (không phải vậy):

fatal: Failed to resolve 'HEAD' as a valid ref.

Nó chỉ ra rằng đó là bởi vì ref (chi nhánh?) Không tồn tại cho đến sau lần cam kết đầu tiên. Đó là, bạn sẽ gặp phải vấn đề tương tự như người mới bắt đầu nếu quy trình làm việc của bạn, như của tôi, là một cái gì đó như:

  1. cd vào thư mục dự án mới tuyệt vời của tôi để dùng thử Git, độ hot mới
  2. git init
  3. git add .
  4. git status

    ... rất nhiều cuộn tào lao bằng ...

    => Chết tiệt, tôi không muốn thêm tất cả.

  5. google "hoàn tác thêm"

    => tìm Stack Overflow - yay

  6. git reset .

    => gây tử vong: Không thể giải quyết 'ĐẦU' dưới dạng tham chiếu hợp lệ.

Nó tiếp tục chỉ ra rằng có một lỗi được ghi lại chống lại sự vô ích của điều này trong danh sách gửi thư.

Và rằng giải pháp chính xác đã có ngay trong đầu ra trạng thái Git (trong đó, vâng, tôi đã nhấn mạnh là 'tào lao)

...
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
...

Và giải pháp thực sự là sử dụng git rm --cached FILE.

Lưu ý các cảnh báo ở nơi khác tại đây - git rmxóa bản sao làm việc cục bộ của tệp, nhưng không xóa nếu bạn sử dụng --cached . Đây là kết quả của git help rm:

--cached Sử dụng tùy chọn này để hủy bỏ và chỉ xóa các đường dẫn khỏi chỉ mục. Các tệp cây làm việc, cho dù có sửa đổi hay không, sẽ được để lại.

Tôi tiến hành sử dụng

git rm --cached .

để loại bỏ mọi thứ và bắt đầu lại. Mặc dù không hoạt động, bởi vì trong khi add .đệ quy, hóa ra rmcần -rphải lặp lại. Thở dài.

git rm -r --cached .

Được rồi, bây giờ tôi trở lại nơi tôi đã bắt đầu. Lần tới tôi sẽ sử dụng -nđể chạy khô và xem những gì sẽ được thêm vào:

git add -n .

Tôi đã nén mọi thứ đến một nơi an toàn trước khi tin tưởng git help rmvề việc --cachedkhông phá hủy bất cứ thứ gì (và nếu tôi viết sai chính tả).


15
Hah Tôi đã làm theo quy trình tương tự. Ngoại trừ tôi đã từ bỏ và nói rm -rf .git, git initbởi vì tôi không tin tưởng git rm --cachedđể giữ bản sao làm việc của mình. Nó nói một chút về cách git vẫn còn quá phức tạp ở một số nơi. git unstagechỉ nên là một lệnh tiêu chuẩn chứng khoán, tôi không quan tâm nếu tôi có thể thêm nó dưới dạng bí danh.
Adrian Macneil

5
Đối với tôi, git nóigit reset HEAD <File>...
drahnr

16
git rm --cached <file> thực sự là câu trả lời đúng, nếu đó là lần nhập đầu tiên của <file> vào kho lưu trữ. Nếu bạn đang cố gắng thay đổi tập tin, git reset là câu trả lời đúng. Mọi người nói rằng câu trả lời này là sai khi nghĩ về một câu hỏi khác.
Barry Kelly

14
Điều này thực sự sẽ hoạt động, nhưng chỉ trên lần xác nhận đầu tiên, nơi tệp không tồn tại trước đó hoặc khi git addlệnh thêm tệp mới, nhưng không thay đổi đối với tệp hiện có.
ness101

4
chỉ đi để cho thấy git không trực quan và phức tạp như thế nào. thay vì có các lệnh "hoàn tác" song song, bạn phải tìm ra cách hoàn tác chúng. Giống như cố gắng giải phóng chân của bạn trên cát nhanh, và sau đó bị kẹt cánh tay, sau đó bị kẹt cánh tay khác ... mọi lệnh nên được thực hiện thông qua GUI, với các mục menu thả xuống cho các tùy chọn ... Hãy nghĩ về tất cả UI, tăng năng suất chúng tôi đã có, nhưng chúng tôi có mớ hỗn độn của giao diện dòng lệnh retro. Nó không giống như các chương trình GUI git làm cho điều này trở nên trực quan hơn.
ahnbizcad

532

Nếu bạn gõ:

git status

Git sẽ cho bạn biết những gì được dàn dựng, v.v., bao gồm các hướng dẫn về cách mở khóa:

use "git reset HEAD <file>..." to unstage

Tôi thấy Git làm một công việc khá tốt là thúc đẩy tôi làm điều đúng đắn trong những tình huống như thế này.

Lưu ý: Các phiên bản Git gần đây (1.8.4.x) đã thay đổi thông báo này:

(use "git rm --cached <file>..." to unstage)

19
Thông báo sẽ khác nhau tùy thuộc vào việc addtệp ed đã được theo dõi hay chưa ( addphiên bản duy nhất được lưu vào bộ đệm - ở đây nó sẽ hiển thị thông báo của bạn). Ở những nơi khác, nếu tập tin không được dàn dựng trước đó, nó sẽ hiển thịuse "git rm --cached <file>..." to unstage
leonbloy

Tuyệt quá! Người git reset HEAD <file>duy nhất sẽ làm việc trong trường hợp bạn muốn
hủy

2
Phiên bản git 2.14.3 của tôi nói git reset HEADvới unstage.
SilverWolf - Phục hồi Monica

246

Để làm rõ: git adddi chuyển các thay đổi từ thư mục làm việc hiện tại sang khu vực tổ chức (chỉ mục).

Quá trình này được gọi là dàn dựng . Vì vậy, các lệnh tự nhiên nhất để giai đoạn thay đổi (thay đổi files) là một rõ ràng:

git stage

git add chỉ là một bí danh dễ gõ hơn cho git stage

Đáng tiếc không có lệnh git unstagecũng không git unadd. Cái có liên quan khó đoán hoặc khó nhớ hơn, nhưng nó khá rõ ràng:

git reset HEAD --

Chúng ta có thể dễ dàng tạo một bí danh cho việc này:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

Và cuối cùng, chúng ta có các lệnh mới:

git add file1
git stage file2
git unadd file2
git unstage file1

Cá nhân tôi sử dụng các bí danh thậm chí ngắn hơn:

git a # For staging
git u # For unstaging

3
"Di chuyển"? Điều này sẽ chỉ ra rằng nó đã đi từ thư mục làm việc. Đó không phải là trường hợp.
Thomas Weller

4
Tại sao nó rõ ràng?
Lenar Hoyt

Trên thực tế, git stagelà bí danh cho git add, đó là mệnh lệnh lịch sử, cả trên Git và SCM khác. Nó đã được thêm vào tháng 12 năm 2008 với cam kết 11920d28da trong "Kho lưu trữ git của Git", nếu tôi có thể nói.
Obsidian

1
Điều này có thể không liên quan, nhưng tôi đã tìm thấy xác nhận tệp trước khi thêm vào là một ý tưởng hữu ích, giống như tên tệp kiểm tra lệnh && git thêm tên tệp, tôi đã thay thế git bằng một g ngắn hơn trong máy của mình và cho đến nay nó đã hoạt động ok cho tôi: github.com/dataf3l/g , tôi không biết điều này có hữu ích với ai đó không, nhưng tôi sẽ đặt nó ở đây với hy vọng nó sẽ tiết kiệm thời gian của mọi người.
Felipe Valdes

167

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 .gitthư 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:

  1. 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ó.

  2. 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 HEADkhông hoạt động, nhưng git rm --cachedthự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 addghi đè 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 -alệ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)


4
Nói đúng ra, có một cách để khôi phục một tập tin đã được dàn dựng đã được thay thế bằng git add. Như bạn đã đề cập, git add tạo ra một đối tượng git cho tệp đó sẽ trở thành một đối tượng lỏng lẻo không chỉ khi xóa tệp hoàn toàn mà cả khi bị ghi đè bằng nội dung mới. Nhưng không có lệnh để tự động phục hồi nó. Thay vào đó, tệp phải được xác định và trích xuất thủ công hoặc với các công cụ chỉ được viết cho trường hợp này (libgit2 sẽ cho phép điều này). Nhưng điều này sẽ chỉ trả tiền nếu tệp rất quan trọng và lớn và không thể được xây dựng lại bằng cách chỉnh sửa phiên bản trước.
Julian Matokic

2
Để tự sửa lỗi: Một khi tệp đối tượng lỏng lẻo được tìm thấy (sử dụng dữ liệu meta như ngày / giờ tạo) git cat-filecó thể được sử dụng để khôi phục nội dung của nó.
Julian Matokic

2
Một cách khác để 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 đè bằng ví dụ khác git addlà thông qua git fsck --unreachableđó sẽ liệt kê tất cả các obj không thể truy cập, sau đó bạn có thể kiểm tra bằng cách git show SHA-1_IDhoặc git fsck --lost-foundsẽ viết các đối tượng lơ lửng vào .git/lost-found/commit/hoặc .git/lost-found/other/tùy theo loại. Xem thêmgit fsck --help
iolsmit

110

Hoàn tác một tệp đã được thêm vào khá dễ dàng bằng Git. Để đặt lại myfile.txt, đã được thêm, sử dụng:

git reset HEAD myfile.txt

Giải trình:

Sau khi bạn dàn dựng (các) tệp không mong muốn, để hoàn tác, bạn có thể làm git reset. Headlà người đứng đầu tệp của bạn tại địa phương và tham số cuối cùng là tên tệp của bạn.

Tôi đã tạo các bước trong hình ảnh bên dưới để biết thêm chi tiết cho bạn, bao gồm tất cả các bước có thể xảy ra trong những trường hợp sau:

git đặt lại tập tin CHÍNH


Hình ảnh: "Lệnh thêm ...""Lệnh thêm ..." (thì hiện tại đơn, người thứ ba )
Peter Mortensen

Hình ảnh: muốnmuốn (không cần sử dụng tiếng lóng ở đây)
Peter Mortensen

92
git rm --cached . -r

sẽ "bỏ thêm" mọi thứ bạn đã thêm từ thư mục hiện tại của mình một cách đệ quy


3
Tôi đã không tìm cách bỏ thêm mọi thứ, chỉ MỘT tệp cụ thể.
paxos1977

3
Cũng hữu ích nếu bạn không có bất kỳ cam kết nào trước đó. Nếu không có cam kết trước đó, git reset HEAD <file>sẽ nóifatal: Failed to resolve 'HEAD' as a valid ref.
Priya Ranjan Singh

6
Không, đây thêm một xóa tất cả mọi thứ trong thư mục hiện tại của bạn. Rất khác nhau để chỉ thay đổi unstaging.
Đánh dấu Amery

88

Chạy

git gui

và xóa tất cả các tệp theo cách thủ công hoặc bằng cách chọn tất cả các tệp và nhấp vào nút tắt từ nút cam kết .


1
Vâng, tôi hiểu điều đó. Tôi chỉ muốn ngầm gợi ý rằng bạn cho biết rằng trong câu trả lời của bạn như "Bạn có thể sử dụng git-gui...." :)
Alexander Suraphel

1
Nó nói, "git-gui: lệnh không tìm thấy". Tôi không chắc chắn nếu điều này làm việc.
Parinda Rajapaksha

Ồ, điều này đơn giản hơn nhiều khi thực hiện các dòng lệnh mà bạn không hiểu. Điều này chắc chắn được khuyến khích cho một người mới bắt đầu như tôi. Cảm ơn vì đã viết cái này lên!
Irfandy Jip

Cảm ơn. Không muốn mạo hiểm nên đã phải sử dụng GUI.
Sagar Khatri

83

Git có các lệnh cho mọi hành động có thể tưởng tượng được, nhưng nó cần kiến ​​thức sâu rộng để làm mọi thứ đúng và do đó nó phản tác dụng tốt nhất ...

Những gì bạn đã làm trước đây:

  • Thay đổi một tập tin và được sử dụng git add ., hoặc git add <file>.

Bạn muốn gì:

  • Xóa tệp khỏi chỉ mục, nhưng giữ nguyên phiên bản và để lại các thay đổi không được cam kết trong bản sao làm việc:

    git reset head <file>
    
  • Đặt lại tệp về trạng thái cuối cùng từ CHÍNH, hoàn tác các thay đổi và xóa chúng khỏi chỉ mục:

    # Think `svn revert <file>` IIRC.
    git reset HEAD <file>
    git checkout <file>
    
    # If you have a `<branch>` named like `<file>`, use:
    git checkout -- <file>

    Điều này là cần thiết vì git reset --hard HEADsẽ không làm việc với các tập tin duy nhất.

  • Xóa <file>khỏi chỉ mục và phiên bản, giữ tệp chưa được phiên bản với các thay đổi trong bản sao làm việc:

    git rm --cached <file>
    
  • Xóa <file>khỏi bản sao làm việc và phiên bản hoàn toàn:

    git rm <file>
    

1
Tôi không thể chịu được sự khác biệt của 'git reset head <file>' và 'git rm --cached <file>. Bạn có thể giải thích nó?
jeswang

6
Các tệp @jeswang là 'được biết' với git (những thay đổi trong chúng đang được theo dõi.) hoặc chúng không được 'phiên bản'. reset headhoàn tác các thay đổi hiện tại của bạn, nhưng tệp vẫn đang được git theo dõi. rm --cachedđưa tệp ra khỏi phiên bản, do đó git không còn kiểm tra các thay đổi nữa (và cũng loại bỏ các thay đổi hiện tại được lập chỉ mục, được bảo là git trước đó add), nhưng tệp đã thay đổi sẽ được giữ trong bản sao làm việc của bạn, đó là trong thư mục tệp của bạn trên ổ cứng.
sjas

3
Sự khác biệt là git reset HEAD <file>tạm thời - lệnh sẽ chỉ được áp dụng cho lần xác nhận tiếp theo, nhưng git rm --cached <file>sẽ bỏ qua cho đến khi nó được thêm lại với git add <file>. Ngoài ra, git rm --cached <file>có nghĩa là nếu bạn đẩy chi nhánh đó vào điều khiển từ xa, bất kỳ ai kéo chi nhánh sẽ nhận được tệp HOẠT ĐỘNG bị xóa khỏi thư mục của họ.
DrewT

80

Câu hỏi không được đặt ra rõ ràng. Lý do là git addcó hai ý nghĩa:

  1. thêm một tập tin mới vào khu vực tổ chức, sau đó hoàn tác với git rm --cached file.
  2. thêm một tập tin sửa đổi vào khu vực tổ chức, sau đó hoàn tác với git reset HEAD file.

Nếu nghi ngờ, hãy sử dụng

git reset HEAD file

Bởi vì nó làm điều mong đợi trong cả hai trường hợp.

Cảnh báo: nếu bạn thực hiện git rm --cached filetrên một tệp đã được sửa đổi (một tệp đã tồn tại trước đó trong kho lưu trữ), thì tệp đó sẽ bị xóa git commit! Nó vẫn sẽ tồn tại trong hệ thống tệp của bạn, nhưng nếu có ai khác thực hiện cam kết của bạn, tệp sẽ bị xóa khỏi cây công việc của họ.

git statussẽ cho bạn biết nếu tệp là một tệp mới hoặc được sửa đổi :

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt

7
+1. Một số lượng lớn các câu trả lời và nhận xét được đánh giá cao trên trang này hoàn toàn sai về hành vi của git rm --cached somefile. Tôi hy vọng câu trả lời này sẽ đưa trang của bạn lên một vị trí nổi bật, nơi nó có thể bảo vệ người mới khỏi bị lừa bởi tất cả các tuyên bố sai.
Đánh dấu Amery

một trong những câu trả lời hay nhất ở đây, thật đáng buồn là nó khá thấp trong danh sách
Creos

64

Nếu bạn đang cam kết ban đầu và bạn không thể sử dụng git reset, chỉ cần tuyên bố "Git phá sản" và xóa .gitthư mục và bắt đầu lại


5
Một mẹo là sao chép tệp .git / config của bạn nếu bạn đã thêm nguồn gốc từ xa, trước khi xóa thư mục.
Tiago

4
@ChrisJohnsen bình luận là tại chỗ. Đôi khi, bạn muốn cam kết tất cả các tệp trừ một: git add -A && git rm --cached EXCLUDEFILE && git commit -m 'awesome commit' (Điều này cũng hoạt động khi không có cam kết trước đó, sự Failed to resolve 'HEAD'cố lại )

57

Theo nhiều câu trả lời khác, bạn có thể sử dụng git reset

NHƯNG:

Tôi tìm thấy bài đăng nhỏ tuyệt vời này thực sự bổ sung lệnh Git (tốt, một bí danh) cho git unadd: xem git unadd để biết chi tiết hoặc ..

Đơn giản,

git config --global alias.unadd "reset HEAD"

Bây giờ bạn có thể

git unadd foo.txt bar.txt

45

Sử dụng git add -iđể xóa các tệp vừa thêm khỏi cam kết sắp tới của bạn. Thí dụ:

Thêm tệp bạn không muốn:

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]#

Đi vào tương tác thêm để hoàn tác add của bạn (các lệnh được nhập tại git ở đây là "r" (hoàn nguyên), "1" (mục đầu tiên trong danh sách hoàn nguyên hiển thị), 'return' để thoát khỏi chế độ hoàn nguyên và "q" (bỏ):

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

Đó là nó! Đây là bằng chứng của bạn, cho thấy "foo" đã trở lại trong danh sách chưa được theo dõi:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$

42

git removehoặc git rmcó thể được sử dụng cho việc này, với --cachedcờ. Thử:

git help rm

9
Đây không phải là sẽ loại bỏ các tập tin hoàn toàn?
Willa

8
git rm --cached ...sẽ xóa các tập tin từ một repo git. Chúng vẫn sẽ tồn tại trên máy tính của bạn, nhưng điều này RẤT khác với những thay đổi không theo dõi đối với một tệp. Đối với bất kỳ ai vấp phải điều này, nó không phải là một câu trả lời hợp lệ cho câu hỏi.
Addison

38

Đây là một cách để tránh vấn đề khó chịu này khi bạn bắt đầu một dự án mới:

  • Tạo thư mục chính cho dự án mới của bạn.
  • Chạy đi git init.
  • Bây giờ hãy tạo một tệp .gitignore (ngay cả khi nó trống).
  • Cam kết tập tin .gitignore của bạn.

Git làm cho nó thực sự khó thực hiện git resetnếu bạn không có bất kỳ cam kết nào. Nếu bạn tạo ra một cam kết ban đầu nhỏ bé chỉ vì muốn có một, sau đó bạn có thể git add -Agit resetbao nhiêu lần bạn muốn để có được mọi thứ đúng.

Một ưu điểm khác của phương pháp này là nếu sau này bạn gặp rắc rối về kết thúc dòng và cần làm mới tất cả các tệp của mình, thật dễ dàng:

  • Kiểm tra cam kết ban đầu. Điều này sẽ loại bỏ tất cả các tập tin của bạn.
  • Sau đó kiểm tra cam kết gần đây nhất của bạn một lần nữa. Điều này sẽ lấy các bản sao mới của các tệp của bạn, bằng cách sử dụng cài đặt kết thúc dòng hiện tại của bạn.

1
Đã xác nhận! Đã thử thiết lập lại git sau khi thêm git. và git đã phàn nàn về ĐẦU CHÍNH. Theo lời khuyên của bạn, tôi có thể git add & reset qua lại mà không gặp vấn đề gì :)
Kounavi

1
Phần thứ hai hoạt động, nhưng nó hơi vụng về. Cách xử lý kết thúc dòng, tùy thuộc vào autocrlfgiá trị ... Điều này sẽ không hoạt động trong mọi dự án, tùy thuộc vào cài đặt.
sjas

1
Câu trả lời này là hợp lý tại thời điểm nó được đăng, nhưng bây giờ đã lỗi thời; git reset somefilegit resetcả hai đều làm việc trước khi thực hiện cam kết đầu tiên, bây giờ. Đây là trường hợp kể từ khi một số Git phát hành trở lại.
Đánh dấu Amery

@MarkAmery, bạn có thể đúng (sẽ rất tuyệt nếu bạn đăng một nguồn cho khẳng định của mình), nhưng vẫn có giá trị khi bắt đầu repo của bạn với một hoặc hai cam kết sạch.
Ryan Lundy

34

Có lẽ Git đã phát triển kể từ khi bạn đăng câu hỏi của bạn.

$> git --version
git version 1.6.2.1

Bây giờ, bạn có thể thử:

git reset HEAD .

Đây phải là những gì bạn đang tìm kiếm.


2
Chắc chắn, nhưng sau đó bạn có câu hỏi tiếp theo về cách một người nên bỏ một trong hai (hoặc nhiều) tệp được thêm vào. Hướng dẫn "git reset" có đề cập rằng "git reset <path>", ngược lại với "git add <path>", tuy nhiên.
Alex North-Keys

34

Lưu ý rằng nếu bạn không chỉ định sửa đổi thì bạn phải bao gồm một dấu phân cách. Ví dụ từ bảng điều khiển của tôi:

git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

git reset -- <path_to_file>
Unstaged changes after reset:
M    <path_to_file>

(Phiên bản Git 1.7.5.4)


2
Tôi đã thử git reset <path>và nó hoạt động tốt mà không cần một dấu phân cách. Tôi cũng đang sử dụng git 1.9.0. Có lẽ nó không hoạt động trong các phiên bản cũ hơn?

31

Để xóa các tệp mới khỏi khu vực tổ chức (và chỉ trong trường hợp tệp mới), như được đề xuất ở trên:

git rm --cached FILE

Chỉ sử dụng rm --cached cho các tệp mới vô tình được thêm vào.


4
Hãy nhớ rằng đây --cachedlà một phần thực sự quan trọng ở đây.
takeshin

1
-1; không, điều này không bỏ tập tin, nó sẽ xóa tập tin (mà không thực sự xóa nó khỏi cây công việc của bạn).
Đánh dấu Amery

25

Để đặt lại mọi tệp trong một thư mục cụ thể (và các thư mục con của nó), bạn có thể sử dụng lệnh sau:

git reset *

4
Trên thực tế, điều này không thiết lập lại mọi tệp vì * sử dụng mở rộng shell và nó bỏ qua các dotfiles (và các thư mục dot).
Lục

Bạn có thể chạy git statusđể xem mọi thứ còn lại và thiết lập lại bằng tay tức là git reset file.
Zorayr

25

Sử dụng *lệnh để xử lý nhiều tệp cùng một lúc:

git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*

Vân vân.


3
Nhớ rằng * sẽ thường không bao gồm dotfiles hoặc 'dot-thư mục' trừ khi bạn chỉ định rõ ràng .*hay.*.prj
Luc

23

Chỉ cần gõ git resetnó sẽ trở lại và nó giống như bạn không bao giờ gõ git add .kể từ lần cam kết cuối cùng của bạn. Hãy chắc chắn rằng bạn đã cam kết trước đó.


Khi điều đó xảy ra, đã có một cam kết cuối cùng ... nhưng tôi đặc biệt hỏi về việc xóa một tệp khỏi cam kết, không phải mọi tệp từ cam kết.
paxos1977

20

Giả sử tôi tạo một tệp mới , newFile.txt:

Nhập mô tả hình ảnh ở đây

Giả sử tôi vô tình thêm tập tin , git add newFile.txt:

Nhập mô tả hình ảnh ở đây

Bây giờ tôi muốn hoàn tác phần bổ sung này, trước khi xác nhận , git reset newFile.txt:

Nhập mô tả hình ảnh ở đây


Giả sử tôi đang ở pic thứ 1 có nghĩa là tôi thậm chí chưa làm "git.add". Ngoài ra, tôi không muốn tất cả sự thay đổi này. Ý tôi là khi tôi làm trạng thái git, nó sẽ không hiển thị bất kỳ tập tin màu đỏ nào. Ý tôi là nó phải được đồng bộ hóa như thể không có một tập tin nào bị thay đổi kể từ lần đẩy git cuối cùng. Làm thế nào để đạt được điều đó.
Không thể phá vỡ

Vì vậy, giả sử bạn chỉ ở bước đầu tiên. Và bạn muốn loại bỏ tất cả những thay đổi bạn đã thực hiện đang khiến "newFile.txt" trở thành màu đỏ.
Không thể phá vỡ

Khi tôi làm tình trạng git. Tôi không nên thấy bất kỳ thay đổi nào cả. Tất cả các tập tin màu đỏ sẽ được hoàn nguyên.
Không thể phá vỡ

Xin chào, tôi nghĩ rằng câu hỏi của bạn là làm thế nào để loại bỏ các tệp không bị theo dõi khỏi cây hiện tại. Vì thế, bạn có thể sử dụng "git clean -f -d". Điều này cũng sẽ loại bỏ các thư mục không bị theo dõi.
Vidura Mudalige

Nếu bạn không muốn xóa các tệp không bị theo dõi, chỉ cần bỏ qua cờ "-f".
Vidura Mudalige

19

Đối với một tệp cụ thể:

  • git đặt lại my_file.txt
  • kiểm tra git my_file.txt

Đối với tất cả các tệp đã thêm:

  • git đặt lại.
  • kiểm tra git.

Lưu ý: thanh toán thay đổi mã trong các tệp và chuyển sang trạng thái cập nhật (đã cam kết) mới nhất. thiết lập lại không thay đổi mã; nó chỉ đặt lại tiêu đề.


3
Hãy giải thích sự khác biệt giữa git reset <file>git checkout <file>.
Trent

1
thiết lập lại không thay đổi tập tin, chỉ cần đặt nó ra khỏi giai đoạn (= index, nơi nó được đặt bởi git add)
franc

kiểm tra thay đổi mã trong tập tin và chuyển sang trạng thái cập nhật cuối cùng. thiết lập lại không thay đổi mã nó chỉ đặt lại tiêu đề. Ví dụ: đặt lại sử dụng cho các tệp được thêm hoặc cam kết đặt lại trước khi sử dụng đẩy và thanh toán để quay lại giai đoạn cập nhật / cam kết cuối cùng trước khi git add.
Hasib Kamal

1
đặt lại = xóa tệp khỏi giai đoạn tuy nhiên những thay đổi sẽ vẫn còn đó. checkout = lấy tệp cập nhật từ kho lưu trữ và sẽ ghi đè tệp hiện tại
Imam Bux

14

Lệnh này sẽ hủy bỏ các thay đổi của bạn:

git reset HEAD filename.txt

Bạn cũng có thể dùng

git add -p 

để thêm các phần của tập tin.


14

Ngoài ra còn có chế độ tương tác:

git add -i

Chọn tùy chọn 3 để bỏ thêm tập tin. Trong trường hợp của tôi, tôi thường muốn thêm nhiều hơn một tệp và với chế độ tương tác, bạn có thể sử dụng các số như thế này để thêm tệp. Điều này sẽ mất tất cả trừ 4: 1, 2, 3 và 5

Để chọn một chuỗi, chỉ cần gõ 1-5 để lấy tất cả từ 1 đến 5.

Git dàn tập tin


"Tôi ngạc nhiên khi không ai đề cập đến chế độ tương tác" - họ đã làm: stackoverflow.com/a/10209776/1709587
Mark Amery


10
git reset filename.txt

Sẽ xóa một tệp có tên filename.txt khỏi chỉ mục hiện tại, khu vực "sắp được cam kết", mà không thay đổi bất cứ điều gì khác.


10

git add myfile.txt # Điều này sẽ thêm tệp của bạn vào danh sách cần cam kết

Hoàn toàn ngược lại với lệnh này là,

git reset HEAD myfile.txt  # This will undo it.

vì vậy, bạn sẽ ở trạng thái trước. Được chỉ định sẽ một lần nữa trong danh sách không theo dõi (trạng thái trước đó).

Nó sẽ thiết lập lại đầu của bạn với tập tin được chỉ định đó. vì vậy, nếu đầu của bạn không có ý nghĩa, nó sẽ đơn giản đặt lại nó.


9

Trong Sourcetree, bạn có thể thực hiện việc này một cách dễ dàng thông qua GUI. Bạn có thể kiểm tra xem Sourcetree sử dụng lệnh nào để hủy tập tin.

Tôi đã tạo một tệp mới và thêm nó vào Git. Sau đó, tôi đã giải thích nó bằng GUI Sourcetree. Đây là kết quả:

Các tập tin chưa được xử lý

Sourcetree sử dụng resetđể bỏ các tập tin mới.


Có, kỹ thuật tương tự có thể được sử dụng với TortoiseGit , nhận các lệnh Git cho các trường hợp sử dụng phổ biến.
Peter Mortensen

8
git reset filename.txt  

Sẽ xóa một tệp có tên filename.txt khỏi chỉ mục hiện tại, khu vực "sắp được cam kết", mà không thay đổi bất cứ điều gì khác.


git reset [tên tệp] ex: git reset src / main / java / com / dao / ImportCsvDataDaoImpl.java
Rohit Chaurasiya
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.