ฉันสามารถลบคอมมิทคอมมิชชัน แต่เก็บการเปลี่ยนแปลงนั้นได้


1055

ในสาขาการพัฒนาของฉันฉันทำการเปลี่ยนแปลงรหัสฐานของฉัน ก่อนที่ฉันจะสามารถใช้งานฟีเจอร์ต่าง ๆ ที่ฉันใช้งานได้ฉันต้องเปลี่ยนสาขาปัจจุบันของฉันเป็นโทเพื่อสาธิตคุณลักษณะบางอย่าง แต่เพียงแค่ใช้ "อาจารย์ชำระเงิน git" รักษาการเปลี่ยนแปลงที่ฉันทำไว้ในสาขาการพัฒนาของฉัน ดังนั้นสิ่งที่ฉันได้กระทำคือการเปลี่ยนแปลงในสาขาการพัฒนาของฉันด้วยข้อความการกระทำ "การกระทำชั่วคราว" และจากนั้นชำระเงินหลักสำหรับการสาธิต

ตอนนี้ฉันได้ทำการสาธิตและกลับไปทำงานในสาขาการพัฒนาของฉันฉันต้องการลบ "การกระทำชั่วคราว" ที่ฉันทำในขณะที่ยังคงรักษาการเปลี่ยนแปลงที่ฉันทำไว้ เป็นไปได้ไหม


65
ครั้งต่อไป:git stash
แมตต์บอล

51
@ MattBall ไม่จำเป็น ในขณะที่git stashเป็นเครื่องมือที่ดีการกระทำที่อยู่ระหว่างดำเนินการก็เป็นสิ่งที่ถูกต้องตามกฎหมายเช่นกัน
kostix

3
นี้เป็นทรัพยากรที่ดีช่องแคบจาก Github: วิธีการยกเลิก (เกือบ) อะไรกับ Git
jasonleonhard

9
@MattBall @kostix ใช่แล้วการซ่อนนั้นเหมาะสมอย่างยิ่งสำหรับการ stashing "ระยะยาว" เนื่องจากเป็นสแต็คระดับโลกเดียวสำหรับการซื้อคืนทั้งหมด ฉันต้องการที่จะซ่อนการเปลี่ยนแปลงในสาขาและจากนั้นไปที่สาขาอื่นทำอะไรก็ได้กลับมาในวันต่อมาโดยไม่ต้องกังวลว่าฉันอาจเคยใช้git stashกับสาขาอื่นในช่วงนั้น
Alec

4
สิ่งหนึ่งที่ควรค่าแก่การสังเกตstashคือมันเป็นแบบโลคัลและจะมีแนวโน้มที่จะเกิดการสูญเสียรหัสจากการลบ repo หรือการพักผ่อนหย่อนใจหรือความล้มเหลวของฮาร์ดแวร์หรือการสูญเสีย IMO ควรใช้กับ WIP ระยะสั้นมาก ๆ เท่านั้น รัก WIP ที่ลงมือทำก่อนจะไปเที่ยว: P .. เรียกมันว่าการถ่ายโอนข้อมูลในสมอง!
ϹοδεMεδιϲ

คำตอบ:


1617

มันง่ายอย่างนี้:

git reset HEAD^

หมายเหตุ: เชลล์บางตัวถือว่า^เป็นอักขระพิเศษ (ตัวอย่างเช่นเชลล์ Windows บางตัวหรือZSH ที่เปิดใช้งานแบบวงกลม ) ดังนั้นคุณอาจต้องอ้างอิง"HEAD^"ในกรณีเหล่านี้

git resetโดยไม่ต้อง--hardหรือ--softย้ายคุณHEADไปชี้ไปที่การกระทำที่ระบุโดยไม่ต้องเปลี่ยนไฟล์ใด ๆ HEAD^อ้างถึงการกระทำหลัก (แรก) ของการกระทำปัจจุบันของคุณซึ่งในกรณีของคุณคือการกระทำก่อนที่จะกระทำการชั่วคราว

โปรดทราบว่าตัวเลือกอื่นคือการดำเนินการตามปกติจากนั้นไปที่จุดยอมรับถัดไปแทนที่จะเรียกใช้:

git commit --amend [-m … etc]

ซึ่งจะแก้ไขการกระทำล่าสุดแทนโดยมีผลเช่นเดียวกับข้างต้น

โปรดทราบว่าสิ่งนี้ (เช่นเดียวกับคำตอบ git เกือบทั้งหมด) อาจทำให้เกิดปัญหาได้หากคุณได้ผลักดันการกระทำที่ไม่ดีไปยังสถานที่ที่มีคนอื่นดึงมันมา พยายามหลีกเลี่ยงสิ่งนั้น


47
นี่เป็นวิธีที่ง่ายที่สุด แต่ถ้าคุณผลักภาระของคุณไปที่รีโมตแล้วและมีคนอื่นดึงมันฉันจะลังเลที่จะทำทุกอย่างยกเว้นขอโทษ
atw13

11
@sophophrenic อย่าพลาดโอกาสในการอ่าน"รีเซ็ต Demystified"ในโอกาสนี้
kostix

33
ฉันได้รับMore?หลังจากทำสิ่งนี้ อะไรก็ตามที่ฉันพิมพ์ในพรอมต์นั้นให้ฉันfatal: ambiguous argument 'HEADwhateverItypedIn': unknown revision or path not in the working tree.
DaAwesomeP

50
@DaAwesomeP ดูเหมือนว่าคุณกำลังใช้เชลล์ซึ่งถือว่า^เป็นอักขระพิเศษ คุณจะสามารถพูดอ้างอิง"HEAD^"หรือใช้ไวยากรณ์ทางเลือกHEAD~1unquoted
แกเร็ ธ

8
ทำงานให้ฉันได้ แต่ต้องหลบหนีจากตัวละครgit reset HEAD\^
cevaris

188

มีวิธีการจัดการสองวิธีนี้ ซึ่งง่ายกว่านั้นขึ้นอยู่กับสถานการณ์ของคุณ

ตั้งค่าใหม่

หากความมุ่งมั่นที่คุณต้องการกำจัดเป็นความมุ่งมั่นครั้งสุดท้ายและคุณยังไม่ได้ทำงานเพิ่มเติมใด ๆ ที่คุณสามารถทำได้ git-reset

git reset HEAD^

นำสาขาของคุณกลับไปสู่ความมุ่งมั่นต่อหน้าหัวหน้าปัจจุบันของคุณ อย่างไรก็ตามมันไม่ได้เปลี่ยนไฟล์ในแผนผังการทำงานของคุณ ดังนั้นการเปลี่ยนแปลงที่เกิดขึ้นในการกระทำที่ปรากฏขึ้นมีการแก้ไข - มันเหมือนคำสั่ง 'ผิดปกติ' อันที่จริงฉันมีนามแฝงที่จะทำเช่นนั้น

git config --global alias.uncommit 'reset HEAD^'

จากนั้นคุณสามารถใช้git uncommitในอนาคตเพื่อสำรองข้อมูลการกระทำ

ฉับ

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

git rebase -i <ref>

ฉันพูดไปแล้วเพราะฉันต้องการทำให้ชัดเจนว่านี่อาจเป็นข้อผูกมัดใด ๆ เรียกใช้git logและพบการกระทำที่คุณต้องการที่จะกำจัดให้คัดลอก SHA1 <ref>และใช้มันในสถานที่ของ Git จะนำคุณเข้าสู่โหมดรีบูตแบบโต้ตอบ <ref>มันจะแสดงทั้งหมดกระทำระหว่างสถานะปัจจุบันของคุณและสิ่งที่คุณใส่ในสถานที่ของ ดังนั้นหาก<ref>10 คอมมิชชันที่ผ่านมาจะแสดงการคอมมิททั้งหมด 10 ครั้ง

pickในด้านหน้าของแต่ละกระทำก็จะมีคำว่า ค้นหากระทำคุณต้องการที่จะได้รับการกำจัดและเปลี่ยนจากpickการหรือfixup squashใช้fixupเพียงทิ้งที่กระทำข้อความและรวมการเปลี่ยนแปลงในบรรพบุรุษของมันทันทีในรายการ squashคำหลักจะเป็นสิ่งเดียวกัน แต่ช่วยให้คุณสามารถแก้ไขข้อความกระทำของใหม่รวมกันกระทำ

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

คำเตือน:

การรีบูตแก้ไขประวัติ - อย่าทำเช่นนี้กับการกระทำใด ๆ ที่คุณได้แชร์ไปแล้วกับนักพัฒนาคนอื่น ๆ

stashing

ในอนาคตเพื่อหลีกเลี่ยงปัญหานี้ให้พิจารณาใช้git stashในการจัดเก็บงานที่ไม่มีข้อผูกมัดชั่วคราว

git stash save 'some message'

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

คุณสามารถเรียกดูรายการที่ซ่อนของคุณด้วย ...

git stash list

สิ่งนี้จะแสดงการหยุดของคุณทั้งหมดสิ่งที่พวกเขาทำในสาขาและข้อความและที่จุดเริ่มต้นของแต่ละบรรทัดและตัวระบุสำหรับที่ซ่อนซึ่งมีลักษณะเช่นนี้stash@{#}โดยที่ # คือตำแหน่งในอาร์เรย์ของการซ่อน

ในการคืนค่าสแต็ค (ซึ่งสามารถทำได้ในทุกสาขาโดยไม่คำนึงถึงตำแหน่งที่สร้างสแตชตั้งแต่แรก) คุณเพียงแค่รัน ...

git stash apply stash@{#}

อีกครั้งมี # คือตำแหน่งในอาร์เรย์ของการหยุดทำงาน หากที่เก็บที่คุณต้องการเรียกคืนอยู่ใน0ตำแหน่ง - นั่นคือหากเป็นที่เก็บล่าสุด git stash applyจากนั้นคุณก็สามารถเรียกใช้คำสั่งโดยไม่ต้องระบุตำแหน่งที่ซ่อนที่คอมไพล์จะถือว่าคุณหมายถึงคนสุดท้าย:

ตัวอย่างเช่นถ้าฉันพบว่าตัวเองทำงานผิดสาขา - ฉันอาจเรียกใช้ลำดับของคำสั่งต่อไปนี้

git stash
git checkout <correct_branch>
git stash apply

ในกรณีของคุณคุณย้ายสาขาไปอีกเล็กน้อย แต่ยังคงมีแนวคิดเดียวกันนี้อยู่

หวังว่านี่จะช่วยได้


6
git config --global alias.uncommit reset HEAD^เพียงนามแฝงเป็นเรื่องธรรมดาที่จะรีเซ็ต แต่ทำgit config --global alias.uncommit 'reset HEAD^'
mernst

3
โปรดทราบว่าคุณจะต้องใช้ ^^ แทน ^ หากใช้ในพรอมต์คำสั่ง windows
Pramod BR

106

ฉันคิดว่าคุณกำลังมองหาสิ่งนี้

git reset --soft HEAD~1

มันยกเลิกการกระทำล่าสุดในขณะที่รักษาการเปลี่ยนแปลงที่ทำไว้ในการแสดงละคร


7
ขอบคุณ สิ่งนี้ใช้ได้สำหรับฉัน การโทรgit reset HEAD^บน Windows จะแจ้งให้ "เพิ่มเติมหรือไม่" - สิ่งที่หมายถึง
Tyron

12
@Tyron ^เป็นตัวหนีใน DOS เมื่อจับคู่กับบรรทัดใหม่มันทำหน้าที่เป็นพรอมต์ต่อเนื่องสำหรับคำสั่งก่อนหน้า การพิมพ์git reset HEAD^^ควรทำงานบน Windows
trk

40

ใช่คุณสามารถลบการกระทำของคุณโดยไม่ลบการเปลี่ยนแปลง: git reset @ ~


7
นี่คือสิ่งที่ฉันต้องการและมันจะเป็นคำตอบที่ยอมรับในความคิดของฉันขอบคุณมาก!
Carlos Liu

2
น่าสนใจ, ไวยากรณ์กะทัดรัด, ฉันไม่เคยเห็นมันใช้มาก่อน มันแตกต่างจากgit reset --softหรือgit reset --keepอย่างไร
user776686

18

คุณกำลังมองหาอย่างใดอย่างหนึ่งหรือgit reset HEAD^ --softgit reset HEAD^ --mixed

คำสั่งรีเซ็ตมี 3 โหมดตามที่ระบุในเอกสาร :

git reset HEAD^ --soft

git commitยกเลิก การเปลี่ยนแปลงยังคงมีอยู่ในแผนผังการทำงาน (โฟลเดอร์โครงการ) + ดัชนี (- แคช)

git reset HEAD^ --mixed

ยกเลิก+git commit git addการเปลี่ยนแปลงยังคงมีอยู่ในแผนผังการทำงาน

git reset HEAD^ --hard

เช่นคุณไม่เคยทำการเปลี่ยนแปลงเหล่านี้ไปยัง codebase การเปลี่ยนแปลงจะหายไปจากแผนผังการทำงาน


9

สำหรับผู้ที่ใช้ zsh คุณจะต้องใช้สิ่งต่อไปนี้:

git reset --soft HEAD\^

อธิบายที่นี่: https://github.com/robbyrussell/oh-my-zsh/issues/449

ในกรณีที่ URL เสียชีวิตส่วนที่สำคัญคือ:

หลบหนี ^ ในคำสั่งของคุณ

คุณสามารถใช้ HEAD ~ เพื่อที่จะได้ไม่ต้องหนีจากมันในแต่ละครั้ง


15
ฉันไม่สามารถจำคำสั่งนี้และต้อง google นี้และหาคำตอบของฉันเอง hahahaha
Greg Hilston

2
git reset HEAD^ทำงานใน zsh สำหรับฉันอาจได้รับการแก้ไขแล้ว
Ben Kolya Mansley

@BenKolyaMansley คุณ zsh เวอร์ชันใดอยู่
เกร็กฮิลสตัน

ฉันกำลังใช้งานzsh 5.3 (x86_64-apple-darwin18.0)
Ben Kolya Mansley

7

ในกรณีของฉันฉันผลักไปที่ repo อุ๊ย!

คุณสามารถย้อนกลับการกระทำที่เฉพาะเจาะจงในขณะที่รักษาการเปลี่ยนแปลงในไฟล์ในเครื่องของคุณได้

git revert -n <sha>

วิธีนี้ฉันสามารถเก็บการเปลี่ยนแปลงที่ฉันต้องการและยกเลิกการกระทำที่ถูกผลักไปแล้ว


ในกรณีของฉันฉันต้องเปลี่ยนสิ่งที่ฉันได้ผลักไปยังที่เก็บระยะไกลแล้ว อุ๊ยยิ่งขึ้น! วิธีที่ดีที่สุดคือgit revert bad-commit-shaจากgit revert -n revert-commit-just-created-shaนั้นซ่อมแซมจากที่นั่น คุณทำให้ฉันครึ่งทาง ขอบคุณ!
TinkerTenorSoftwareGuy

ดูเหมือนว่าจะทำตรงข้ามใช่ไหม? มันสร้างการเปลี่ยนแปลงใหม่ซึ่งสอดคล้องกับการย้อนกลับของการเปลี่ยนแปลงที่ทำในการกระทำที่เลือก หากคุณต้องยอมรับการเปลี่ยนแปลงใหม่เหล่านี้คุณจะต้องยกเลิกงานที่คุณต้องการเก็บไว้จริง ๆ
svaens

3

การใช้ git 2.9 (อย่างแม่นยำ 2.9.2.windows.1) git reset HEAD^จะแสดงข้อความมากขึ้น ไม่แน่ใจว่าใส่อะไรที่นี่ โปรดดูภาพหน้าจอด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

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

ดูภาพหน้าจอด้านล่างที่แสดงgit reset HEAD~1การทำงาน: ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


คุณอาจต้องหลีกเลี่ยงอักขระ ^ - ลองรีเซ็ต git "HEAD ^" หรือรีเซ็ต git HEAD \ ^
ทำเครื่องหมายว่าฟิชเชอร์

เมื่อเพิ่มสิ่งนี้ HEIT ^^ จะถูกรีเซ็ตเป็นบรรทัดใหม่
John Oss

2

อีกหนึ่งวิธีที่จะทำ

เพิ่มคอมมิชชันที่ด้านบนของการคอมมิตชั่วคราวจากนั้นทำ:

git rebase -i

ในการรวมสองคอมมิตเข้าด้วยกัน (คำสั่งจะเปิดไฟล์ข้อความพร้อมคำแนะนำที่ชัดเจนให้แก้ไข)


2
เทคนิคที่ถูกต้อง git reset HEAD^แต่ไม่มีที่ไหนเลยใกล้เป็นสง่างามเป็นเพียงแค่ทำ Git rebase มีที่ว่างมากมายสำหรับข้อผิดพลาดที่นี่
TheBuzzSaw

0

2563 วิธีง่าย ๆ :

git reset <commit_hash>

(แฮชการคอมมิชชันของการคอมมิทล่าสุดที่คุณต้องการเก็บไว้)

หากความมุ่งมั่นถูกผลักคุณสามารถทำ:

git push -f

คุณจะเก็บการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดไว้ในเครื่อง

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