ฉันจะ unstage ไฟล์ของฉันอีกครั้งหลังจากทำการคอมมิทท้องถิ่น?


268

ฉันได้ดำเนินการคำสั่งต่อไปนี้

git add <foo.java>
git commit -m "add the foo.java file"

ฉันจะลบการมอบหมายในพื้นที่ของฉันตอนนี้และยกเลิกขั้นตอน foo.java ได้อย่างไร

หากฉันพิมพ์git reset --hardฉันพบว่ามันเปลี่ยนกลับfoo.javaไปเป็นค่าเดิม

คำตอบ:


451

git reset --soft HEAD~1ควรทำสิ่งที่คุณต้องการ หลังจากนี้คุณจะมีการเปลี่ยนแปลงครั้งแรกในดัชนี (มองเห็นได้ด้วยgit diff --cached) และการเปลี่ยนแปลงล่าสุดของคุณจะไม่มีการจัดฉาก git statusจะมีลักษณะเช่นนี้:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.java
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   foo.java
#

จากนั้นคุณสามารถทำgit add foo.javaและยอมรับการเปลี่ยนแปลงทั้งสองได้ในคราวเดียว


ฉันแก้ไขคำตอบ: "การเปลี่ยนแปลงที่จะเกิดขึ้น" มีการเปลี่ยนแปลงครั้งแรกและ "การเปลี่ยนแปลงที่ไม่ได้จัดเตรียมไว้สำหรับการส่งมอบ" มีการเปลี่ยนแปลงครั้งที่สอง
Antti

4
สิ่งที่อธิบายไว้ในคำตอบนี้คือสิ่งที่git commit --amendทำ แต่ด้วยเวิร์กโฟลว์ที่ซับซ้อนมากขึ้น สิ่งนี้ไม่ได้ตอบคำถามที่ OP ถามทั้งๆที่มีทิศทางที่ดี ( git reset)
7heo.tk

2
ต้องเปลี่ยน '^' ด้วย '~' เพื่อให้มันทำงานได้ดังนั้น:git reset --soft HEAD~
Shahar

3
ทำการรีเซ็ต git - soft HEAD ~ 1 จากนั้น git reset HEAD
Joko Wandiro

คำตอบที่สมบูรณ์แบบกับสิ่งที่ฉันต้องการ!
DeepInJava

78

ใช้:

git reset HEAD^

นั่นเป็นการรีเซ็ต "แบบผสม" โดยค่าเริ่มต้นซึ่งจะทำสิ่งที่คุณถาม ทำให้ foo.java ไม่อยู่ในสถานะลบการคอมมิทล่าสุด


2
คุณจะอธิบายให้ฉันดูได้ไหมว่าการรีเซ็ต "แบบผสม" การรีเซ็ตแบบ "อ่อน" และการรีเซ็ตแบบ "ยาก" คืออะไร
Kit Ho

1
@Kit Ho - คู่มือการรีเซ็ต git มีคำอธิบายที่ยอดเยี่ยมเกี่ยวกับสิ่งเหล่านี้
manojlds

4
@Kit, @manojlds: stackoverflow.com/questions/2530060/ก็ทำเช่นนั้น(ปลั๊กไร้ยางอาย)
Cascabel

5
นั่นคือคำตอบที่ถูกต้องเท่านั้น คำตอบอีกสองข้อจะจัดระยะไฟล์อีกครั้งหลังจากคอมมิท
7heo.tk

git reset --softใช้งานไม่ได้ แต่git reset HEAD^ทำ
wordforthewise

43

สำหรับฉันแล้ววิธีการดังต่อไปนี้สามารถอ่านได้ (ดีกว่า):

git reset HEAD~1

แทนที่จะ1มีข้อผูกพันใด ๆ ที่คุณต้องการให้เลิกทำ


39

git reset --softมีไว้สำหรับ: มันเป็นเหมือนgit reset --hardแต่ไม่ได้สัมผัสไฟล์


4
นั่นเป็นคำอธิบายที่เข้าใจง่ายที่สุดที่ฉันเคยได้ยิน (เพียง 11 คำ)! ขอบคุณ!
phreakhead

3
คำตอบนั้นผิด git reset"เป็นเหมือนgit reset --hardแต่ไม่ได้สัมผัสไฟล์". git reset --softไม่ git reset --softจะจัดการการเปลี่ยนแปลงดังนั้นคุณจะไม่ต้องเพิ่มการแสดงละครในกรณีที่คุณต้องการคอมมิท แต่คุณจะต้องทำการเปลี่ยนแปลงgit reset(ใช่เป็นครั้งที่สองและไม่มี--soft) ในกรณีที่คุณไม่ต้องการ ดังนั้นคำตอบนั้นสั้น แต่ไม่ถูกต้อง
7heo.tk

12

สำหรับการยกเลิกการจัดเก็บไฟล์ทั้งหมดในการกระทำครั้งสุดท้ายของคุณ -

git reset HEAD~


8

"รีเซ็ต" เป็นวิธียกเลิกการเปลี่ยนแปลงในเครื่อง เมื่อกระทำคุณต้องเลือกการเปลี่ยนแปลงเพื่อรวมไว้ใน " git add " - ที่เรียกว่า "staging" และเมื่อการเปลี่ยนแปลงถูกจัดฉากแล้วคุณ " คอมไพล์ยอมรับ " พวกเขา

หากต้องการกลับออกจากการแสดงละครหรือการกระทำคุณต้อง "รีเซ็ต" HEAD ในสาขา HEAD เป็นตัวแปร git ที่ชี้ไปที่การคอมมิทล่าสุด ดังนั้นหากคุณจัดฉาก แต่ยังไม่ได้ทำคุณจะต้อง " ตั้งค่า Git HEAD " ซึ่งย้อนกลับไปที่ HEAD ปัจจุบันโดยทำการเปลี่ยนแปลงจากเวที มันย่อมาจาก " git reset - ผสม HEAD ~ 0 "

หากคุณได้ยืนยันแล้ว HEAD ได้ก้าวหน้าไปแล้วดังนั้นคุณจึงต้องสำรองข้อมูลการยืนยันก่อนหน้านี้ ที่นี่คุณ " รีเซ็ต HEAD ~ 1 " หรือ " รีเซ็ต HEAD ^ 1 " หรือ " รีเซ็ต HEAD ~ " หรือ " รีเซ็ต HEAD ^ " - อ้างอิงทั้งหมด HEAD ลบหนึ่ง

สัญลักษณ์ไหนดีกว่า ~ หรือ ^ คิดว่า ~ tilde เป็นกระแสเดี่ยว - เมื่อแต่ละการกระทำมีผู้ปกครองคนเดียวและเป็นเพียงชุดของการเปลี่ยนแปลงตามลำดับคุณสามารถอ้างอิงการสำรองข้อมูลโดยใช้ตัวหนอนเช่น HEAD ~ 1, HEAD ~ 2, HEAD ~ 3, สำหรับผู้ปกครอง, ปู่ย่าตายาย, ปู่ย่าตายาย, ฯลฯ (โดยทางเทคนิคคือการค้นหาผู้ปกครองคนแรกในรุ่นก่อน ๆ )

เมื่อมีการรวมการกระทำจะมีผู้ปกครองมากกว่าหนึ่งคน นั่นคือเมื่อ ^ caret เข้ามาเล่น - คุณสามารถจำได้เพราะมันแสดงให้เห็นถึงสาขาที่มารวมกัน การใช้เครื่องหมายรูปหมวก HEAD ^ 1 จะเป็นผู้ปกครองคนแรกและ HEAD ^ 2 จะเป็นผู้ปกครองรายที่สองของการกระทำเดียว - แม่และพ่อเช่น

ดังนั้นหากคุณเพียงแค่ย้อนกลับไปหนึ่ง hop ในคอมมิชชันหลักเดียวแล้ว HEAD ~ และ HEAD ^ จะเทียบเท่า - คุณสามารถใช้อย่างใดอย่างหนึ่ง

นอกจากนี้การตั้งค่าสามารถ--soft , --mixedหรือ--hard ซอฟต์รีเซ็ตเพียงแค่คืนค่าคอมมิชชัน - จะรีเซ็ต HEAD แต่จะไม่ตรวจสอบไฟล์จากการคอมมิชชันก่อนหน้าดังนั้นการเปลี่ยนแปลงทั้งหมดในไดเรกทอรีการทำงานจะถูกเก็บไว้ และ - การรีเซ็ตแบบซอฟท์แวร์นั้นไม่ได้ล้างเวที (หรือที่รู้จักกันในชื่อดัชนี ) ดังนั้นไฟล์ทั้งหมดที่ถูกจัดฉากจะยังคงอยู่บนเวที

- รีเซ็ตผสม (ค่าเริ่มต้น) ยังไม่ได้ตรวจสอบไฟล์จากการกระทำก่อนหน้านี้เพื่อให้การเปลี่ยนแปลงทั้งหมดจะถูกเก็บไว้ แต่ขั้นตอนจะถูกล้าง นั่นเป็นเหตุผลที่ " HEIT reset HEAD " ที่เรียบง่ายจะล้างออกจากเวที

- รีเซ็ตฮาร์ดรีเซ็ตหัวและมันจะล้างเวที แต่มันยังตรวจสอบไฟล์ทั้งหมดจากการกระทำก่อนหน้านี้เพื่อให้มันเขียนทับการเปลี่ยนแปลงใด ๆ

หากคุณส่งการกระทำไปยังที่เก็บข้อมูลระยะไกลการรีเซ็ตไม่ทำงานได้ดีนัก คุณสามารถรีเซ็ตภายในเครื่องได้ แต่เมื่อคุณพยายามผลักไปที่รีโมต git จะเห็นว่า HEAD ในพื้นที่ของคุณอยู่ด้านหลัง HEAD ในรีโมตสาขาและจะปฏิเสธที่จะผลักดัน คุณอาจสามารถบังคับให้กดได้ แต่คอมไพล์ไม่ชอบทำสิ่งนั้น

หรือคุณสามารถซ่อนการเปลี่ยนแปลงของคุณหากคุณต้องการเก็บไว้ตรวจสอบการคอมมิชชันก่อนหน้ายกเลิกการสะสมการเปลี่ยนแปลงระยะการสร้างการคอมมิชชันใหม่


+1 สำหรับคำอธิบายโดยละเอียดของการดำเนินการ IMO นี้ควรเป็นคำตอบที่ยอมรับได้!
ISAE

2

ให้บอกว่าคุณต้องการหยุดการเปลี่ยนแปลงไม่เกิน n คอมมิต

ตำแหน่งที่กระทำการแฮ็ชมีดังนี้:

  • h1
  • h2 ...
  • HN
  • HN + 1

จากนั้นรันคำสั่งต่อไปนี้:
git reset hn

ตอนนี้ HEAD จะอยู่ที่ hn + 1 การเปลี่ยนแปลงจาก h1 เป็น hn จะไม่มีการจัดฉาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.