นอกเหนือจากคำตอบที่ยอมรับแล้วหากไฟล์ที่เพิ่มผิดพลาดของคุณมีขนาดใหญ่มากคุณอาจสังเกตเห็นว่าแม้หลังจากลบไฟล์นั้นออกจากดัชนีด้วย ' git reset
' แล้วก็ยังดูเหมือนว่าจะมีพื้นที่ว่างใน.git
ไดเรกทอรี
นี่คือไม่มีอะไรต้องกังวลเกี่ยวกับ; ไฟล์ยังคงอยู่ในที่เก็บ แต่เป็นเพียง "วัตถุหลวม" มันจะไม่ถูกคัดลอกไปยังที่เก็บอื่น ๆ (ผ่านการโคลน, การพุช) และในที่สุดพื้นที่จะถูกเรียกคืน - แม้ว่าอาจจะไม่เร็ว ๆ นี้ หากคุณกังวลคุณสามารถเรียกใช้:
git gc --prune=now
อัปเดต (สิ่งต่อไปนี้คือความพยายามของฉันในการกำจัดความสับสนบางอย่างที่อาจเกิดขึ้นจากคำตอบที่ upvoted ที่สุด):
ดังนั้นซึ่งเป็นจริงเลิกทำของgit add
?
git reset HEAD <file>
?
หรือ
git rm --cached <file>
?
พูดอย่างเคร่งครัดและถ้าฉันไม่ผิด: ไม่มี
git add
ไม่สามารถยกเลิกได้ได้อย่างปลอดภัยโดยทั่วไป
ลองนึกถึงสิ่งแรกที่ควรgit add <file>
ทำ:
หาก<file>
ได้รับไม่ได้ติดตามก่อนหน้านี้ , git add
จะเพิ่มไปยังแคชที่มีเนื้อหาปัจจุบัน
หาก<file>
ได้รับการติดตามแล้ว , git add
บันทึกเนื้อหาปัจจุบัน (ภาพรวมรุ่น) ไปยังแคช ใน Git การกระทำนี้ยังคงเรียกว่าเพิ่ม (ไม่ใช่แค่อัปเดต ) เนื่องจากสองเวอร์ชันที่แตกต่างกัน (สแนปชอต) ของไฟล์ถือเป็นสองรายการที่แตกต่างกัน: ดังนั้นเราจึงเพิ่มรายการใหม่ลงในแคช มุ่งมั่นในภายหลัง
เมื่อพิจารณาถึงสิ่งนี้คำถามจะคลุมเครือเล็กน้อย:
ฉันเพิ่มไฟล์ผิดโดยใช้คำสั่ง ...
สถานการณ์ของ OP น่าจะเป็นไฟล์แรก (ไฟล์ที่ไม่ได้ติดตาม) เราต้องการให้ "เลิกทำ" เพื่อลบไฟล์ (ไม่ใช่แค่เนื้อหาปัจจุบัน) ออกจากรายการที่ถูกติดตาม หากเป็นกรณีนี้แสดงว่าไม่สามารถทำงาน git rm --cached <file>
ได้
และเราก็สามารถวิ่งgit reset HEAD <file>
ได้ สิ่งนี้เป็นสิ่งที่ดีกว่าเพราะมันใช้งานได้ในทั้งสองสถานการณ์: มันจะทำการเลิกทำเมื่อเราเพิ่มเวอร์ชันของรายการที่ถูกติดตามไปอย่างผิด ๆ
แต่มีสองประการ
ครั้งแรก: มี (ตามที่ระบุไว้ในคำตอบ) มีเพียงหนึ่งสถานการณ์ที่git reset HEAD
ไม่สามารถใช้งานได้ แต่git rm --cached
ทำได้: ที่เก็บใหม่ (ไม่มีข้อผูกมัด) แต่จริงๆแล้วนี่เป็นกรณีที่ไม่เกี่ยวข้องในทางปฏิบัติ
ข้อสอง: โปรดทราบว่าgit reset HEAD
ไม่สามารถกู้คืนเนื้อหาไฟล์ที่แคชไว้ก่อนหน้าได้อย่างน่าอัศจรรย์เพียงแค่ซิงโครไนซ์ไฟล์จาก HEAD อีกครั้ง หากเราเข้าใจผิดgit add
เขียนทับเวอร์ชันที่ไม่มีข้อผูกมัดฉากก่อนหน้าเราจะไม่สามารถกู้คืนได้ นั่นเป็นเหตุผลที่พูดอย่างเคร่งครัดเราไม่สามารถยกเลิก [*]
ตัวอย่าง:
$ 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
แน่นอนว่ามันไม่สำคัญมากหากเราเพียงแค่ทำตามขั้นตอนการทำงานแบบสันหลังยาวของการทำ 'git add' เท่านั้นสำหรับการเพิ่มไฟล์ใหม่ (กรณีที่ 1) และเราอัพเดทเนื้อหาใหม่ผ่านgit commit -a
คำสั่งcommit,
* (แก้ไข: ด้านบนถูกต้องจริง แต่ก็ยังสามารถมีวิธีแฮ็ค / convoluted เล็กน้อยสำหรับการกู้คืนการเปลี่ยนแปลงที่ staged แต่ไม่ได้มุ่งมั่นแล้วเขียนทับ - ดูความคิดเห็นโดย Johannes Matokic และ iolsmit)
HEAD
หรือhead
สามารถใช้@
ในสถานที่ของHEAD
แทน ดูคำตอบนี้ (ส่วนสุดท้าย)เพื่อเรียนรู้ว่าทำไมคุณสามารถทำเช่นนั้น