เลิกทำการผสาน Git ที่ยังไม่ได้ผลัก


3942

ภายในสาขาหลักของฉันฉันทำgit merge some-other-branchในพื้นที่ แต่ไม่เคยผลักดันการเปลี่ยนแปลงไปยังจุดเริ่มต้น ฉันไม่ได้ตั้งใจผสานดังนั้นฉันต้องการยกเลิก เมื่อทำการgit statusผสานหลังจากฉันได้รับข้อความนี้:

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

ตามคำแนะนำที่ฉันพบฉันพยายามวิ่ง

git revert HEAD -m 1

แต่ตอนนี้ฉันได้รับข้อความนี้ด้วยgit status:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

ฉันไม่ต้องการให้สาขาของฉันไปข้างหน้าด้วยจำนวนการกระทำใด ๆ ฉันจะกลับไปยังจุดนั้นได้อย่างไร


3
หากคุณต้องการเก็บประวัติไว้ในคำอื่น ๆ มีการเปลี่ยนแปลงที่ทุกคนเคยดึงมาจากคุณหรือคุณผลักมันไปที่ไหนสักแห่งใช้วิธีแก้ปัญหาใน Yuri Ushakov ตอบลงด้านล่าง!
Sedrik

6
โปรดยกเลิกการเลือกคำตอบที่ชนะในปัจจุบัน แต่ก็ไม่ปลอดภัย สำหรับฉัน "MBO" - ดูดีที่สุดแม้ว่าจะมีคะแนนน้อยลง
inger


ที่เกี่ยวข้อง: ย้อนกลับไปยัง Git ก่อนกระทำ

3
นี่เป็นแหล่งข้อมูลที่ยอดเยี่ยมจาก Github: วิธีการยกเลิก (เกือบ) ทุกอย่างกับ Git
jasonleonhard

คำตอบ:


4457

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

git reset --hard commit_sha

นอกจากนี้ยังมีวิธีอื่น:

git reset --hard HEAD~1

มันจะทำให้คุณได้รับการสนับสนุน 1 ครั้ง

โปรดทราบว่าการแก้ไขและปราศจากข้อผูกมัดไฟล์ / unstashed จะถูกรีเซ็ตรัฐยังไม่แปรของพวกเขา หากต้องการให้มีการเปลี่ยนแปลงซ่อนอยู่หรือดู--mergeตัวเลือกด้านล่าง


ตามที่ @Velmont แนะนำด้านล่างในคำตอบของเขาในกรณีตรงนี้โดยใช้:

git reset --hard ORIG_HEAD

อาจให้ผลลัพธ์ที่ดีขึ้นตามที่ควรรักษาการเปลี่ยนแปลงของคุณ ORIG_HEADจะชี้ไปที่การกระทำโดยตรงก่อนที่จะเกิดการผสานดังนั้นคุณไม่ต้องไปหามันด้วยตัวเอง


เคล็ดลับเพิ่มเติมคือใช้--mergeสวิตช์แทน--hardเนื่องจากไม่ได้รีเซ็ตไฟล์โดยไม่จำเป็น:

git reset --merge ORIG_HEAD

--merge

รีเซ็ตดัชนีและอัพเดตไฟล์ในแผนผังการทำงานที่แตกต่างกันระหว่าง <commit> และ HEAD แต่เก็บไว้ซึ่งแตกต่างกันระหว่างดัชนีและแผนผังการทำงาน (เช่นที่มีการเปลี่ยนแปลงที่ยังไม่ได้เพิ่ม)


129
ฉันไม่คิดว่าสิ่งนี้จะได้ผลเสมอไปหรือไม่ "การรวมก่อนหน้านี้" จะเป็นการกระทำล่าสุดที่รวมเข้าด้วยกันจากสาขาอื่น - จะไม่เป็นการกระทำล่าสุดในสาขาปัจจุบัน . ขวา? (นี่อาจเป็นผลมาจากสิ่งที่git logเลือกที่จะแสดงตามค่าเริ่มต้น - อาจจะมีเอาท์พุทที่แตกต่างกันgit logหรือgit reflogสามารถใช้สำหรับเรื่องนี้)
จอห์นบากีร์

6
ฉันคิดว่ามันอาจขึ้นอยู่กับว่าคุณจะรวมสควอช
Marcin Gil

29
@JohnBachir ถูกต้อง ในgit logผลลัพธ์คุณต้องการดูการกระทำหลักสองรายการ หนึ่งคือความมุ่งมั่นล่าสุดในสาขาของคุณหนึ่งคือความมุ่งมั่นล่าสุดในสาขาที่คุณรวมเข้าด้วยกัน คุณต้องการให้git reset --hardผู้ปกครองกระทำในสาขาที่คุณรวมเข้าด้วยกัน
Justin

7
@JohnBachir: ตราบใดที่ "การผสาน" ไม่ใช่การส่งต่อที่รวดเร็วมันจะส่งผลให้เกิดการกระทำใหม่ที่อยู่ด้านบนสุดของบันทึกและการกระทำนี้มีผู้ปกครองสองคน (หรือมากกว่า 2 หากคุณทำปลาหมึกยักษ์ ผสาน) หากคุณลบการรวมการกระทำนี้การกระทำที่เก่ากว่าทั้งหมดที่เข้ามาในการรวมจะหายไปเช่นกัน เพื่อความปลอดภัยแม้ว่าหลังจากคอมไพล์รีเซ็ตแล้วจะบอกคุณว่าส่วนหัวใหม่คือ: "HEAD ตอนนี้ที่ 88a04de <commit message>" ฉันมักจะมองไปที่นั้นเพื่อให้แน่ใจว่าฉันจะลงเอยที่ที่คาดว่าจะเป็น โครงการของฉันใช้รูปแบบการตั้งชื่อสาขามาตรฐานเพื่อให้สิ่งต่าง ๆ น่าจดจำ
Mark E. Haase

44
สิ่งที่ฉันพบว่ามีประโยชน์คือดู "refit คอมไพล์" และมองหาการกระทำสุดท้ายที่ฉันทำในต้นแบบ จากนั้นทำgit reset --hard <commit_sha>
Max Williams

1455

สมมติว่าต้นแบบในพื้นที่ของคุณไม่ได้มาจากต้นกำเนิด / ต้นแบบคุณควรจะสามารถทำได้

git reset --hard origin/master

จากนั้นในท้องถิ่นของคุณสาขาควรมีลักษณะเหมือนกับmasterorigin/master


71
@Carter จริง ๆ แล้วมันไม่ใช่คำตอบที่ดีที่สุด เป็นไปได้ว่าต้นกำเนิด / ต้นแบบอาจนำหน้าต้นแบบในพื้นที่ของคุณก่อนหน้าการรวมกลุ่มโดยการกระทำบางอย่างในกรณีนี้อาจไม่ให้ผลลัพธ์ที่ต้องการ
Dhruva Sagar

15
@ dhruva-sagar ใช่ แต่ตราบใดที่คอมไพล์ไม่ได้บอกว่าคุณอยู่ข้างหลังและคุณไม่สามารถดึงกลับมาได้คุณควรจะสบายดี
Kelvin

3
ขอบคุณ! นี่คือที่สมบูรณ์แบบถ้า (และถ้าเท่านั้น) คุณมีพื้นที่เก็บข้อมูลระยะไกล
tomc

2
ไม่มันไม่ใช่คำถามที่สมบูรณ์แบบสำหรับคำถามนี้ดูข้อ "สมมติ" คำตอบของ MBO ครอบคลุมถึงกรณีนี้จริง ๆ และกรณีที่การผสานไม่ใช่การกระทำในเครื่องเดียว
inger

2
อีกครั้งบางทีคำเตือนนี้ควรเข้าไปในคำตอบของตัวเอง: หลีกเลี่ยงการเขียนประวัติคอมไพล์อีกครั้ง!
cregox

1175

ดูบทที่ 4 ในหนังสือเล่ม Gitและโพสต์ต้นฉบับโดย Linus Torvalds

หากต้องการยกเลิกการรวมที่ผลักแล้ว :

git revert -m 1 commit_hash

อย่าลืมเปลี่ยนกลับถ้าคุณกำลังทำสาขาอีกครั้งอย่างที่ไลนัสพูด


10
@perfectionist เห็นด้วย :) มีความปรารถนาที่จะโยกย้ายคำตอบไปยังคำถามอื่น - (อาจจะมี?)
mikermcneil

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเปลี่ยนกลับ: link
assaqqaf

1
เพื่อให้มั่นใจว่าการคืนค่านี้ใช้งานได้คุณสามารถทำคอมไพล์ hash1 hash2โดยที่ hash1 เป็นการแปลงกลับที่ถูกคอมมิตและ hash2 เป็นคอมมิชชันเก่าที่คุณพยายามจะย้อนกลับไป ไม่มีผลลัพธ์ == สำเร็จ! ฉันสามารถย้อนกลับหลายคอมมิชชันด้วยการทำเช่นนี้หลายครั้งเริ่มต้นด้วยการคืนค่าการผสานล่าสุดและทำงานย้อนหลัง git diffแสดงให้ฉันเห็นว่าฉันลงเอยในสถานะที่ฉันต้องการ
Robert Sinton

6
ขอให้สังเกตว่านี้ไม่ได้จริงแก้คำถามโปสเตอร์เดิม โปสเตอร์เดิมอยู่แล้วgit revert -m 1 <commit>มาใช้ ปัญหาคือการทำเช่นนั้นไม่ได้ลบการผสานโดยบังเอิญที่เขาทำ (และยังไม่ได้ผลัก) คำตอบอื่น ๆ ที่เกี่ยวข้องกับการรีเซ็ตฮาร์ดจะดีกว่าสำหรับปัญหาของโปสเตอร์ต้นฉบับ

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

986

มันแปลกที่คำสั่งที่ง่ายที่สุดหายไป คำตอบส่วนใหญ่ทำงานได้ แต่การยกเลิกการผสานที่คุณเพิ่งทำนี่เป็นวิธีที่ง่ายและปลอดภัย :

git reset --merge ORIG_HEAD

การอ้างอิงORIG_HEADจะชี้ไปที่การส่งต้นฉบับจากก่อนที่จะรวม

( --mergeตัวเลือกไม่มีส่วนเกี่ยวข้องกับการผสานเหมือนgit reset --hard ORIG_HEADกัน แต่ปลอดภัยกว่าเพราะจะไม่ได้สัมผัสการเปลี่ยนแปลงที่ไม่ได้ผูกมัด)


17
หากคุณทำให้ต้นไม้ทำงานของคุณสกปรกให้git reset --merge ORIG_HEADเก็บการเปลี่ยนแปลงเหล่านั้นไว้
yingted

1
นี่เป็นคำตอบเดียวที่ถูกต้อง (ฉันไม่ได้บอกว่านี่เป็นคำตอบที่ดีที่สุด - สังเกตความแตกต่าง) สมมติว่าในปรมาจารย์ฉันทำ 3 คอมมิทที่ t1, t3 และ t5 สมมติว่าใน branch1 ฉันได้ 3 ความคิดเห็นที่ t2, t4 และ t6 (สมมติว่า t1, t2, t3, t4, t5 และ t6 ตามลำดับเวลา) คำสั่งใด ๆ ที่คล้ายกับgit reset --hard HEAD~5จะรีเซ็ต HEAD เท่านั้น (อาจลบการกระทำในทั้งมาสเตอร์และ branch1) เพียงตัวเลือกเอา--merge merge
มนู Manjunath

@Manu --mergeตัวเลือกไม่ได้ลบการผสานจริงๆคุณสามารถใช้--hardงานได้เช่นกัน มันคือการอ้างอิง ORIG_HEAD นั่นเป็นเงื่อนงำที่นี่มันถูกตั้งค่าก่อนที่คุณจะรวมกับตำแหน่งที่คุณยืนอยู่ ณ จุดนั้น :)
odinho - Velmont

@ ถึงสิ่งที่คุณหมายถึง "ถ้าคุณทำให้ต้นไม้ทำงานสกปรกตั้งแต่นั้นให้ตั้งค่าคอมไพล์ - รวม ORIG_HEAD รักษาการเปลี่ยนแปลงเหล่านั้นไว้" คุณหมายถึงเปลี่ยนไฟล์หลังจากรวมหรือไม่ อย่างไรก็ตามฉันได้รวมแล้วทำการแก้ไขข้อขัดแย้งบางอย่าง แต่ฉันต้องการรีเซ็ตการรวมและทำตามคำแนะนำในคำตอบนี้ ทุกอย่างก็โอเคและมันไม่ได้รักษาการเปลี่ยนแปลงของฉันไว้หลังจากรวม repo ในพื้นที่ของฉันนั้นคล้ายกับตำแหน่งก่อนที่ฉันจะรวม
Samitha Chathuranga

git reset --hard ORIG_HEADคำสั่งทำงานอย่างสมบูรณ์สำหรับฉัน - มันอาจจะได้รับความช่วยเหลือจากความจริงที่ว่าผมไม่ได้ทำการเปลี่ยนแปลงอื่น ๆ ที่เก็บหลังจากที่ท้องถิ่นgit mergeผมพยายามที่จะเลิกทำ คำสั่งเพียงรีเซ็ตสถานะของที่เก็บกลับไปเป็นเหมือนก่อนที่จะรวม ขอบคุณสำหรับเคล็ดลับที่ยอดเยี่ยม!
bluebinary

391

ด้วยเวอร์ชัน Git ที่ใหม่กว่าถ้าคุณยังไม่ได้รวมการผสานและคุณมีข้อขัดแย้งในการผสานคุณสามารถทำได้ดังนี้

git merge --abort

จากman git merge:

[สิ่งนี้] สามารถเรียกใช้ได้หลังจากการผสานทำให้เกิดข้อขัดแย้ง git merge --abortจะยกเลิกกระบวนการผสานและพยายามสร้างสถานะ pre-merge ใหม่


8
การผสานของเขามีความมุ่งมั่น แต่ไม่ได้ผลัก (ดูชื่อ) เขาได้รวมแล้วคำสั่งของคุณจะทำงานเฉพาะเมื่อเขายังอยู่ในระหว่างการรวม
JBoy

135

คุณควรรีเซ็ตการกระทำก่อนหน้านี้ สิ่งนี้น่าจะใช้ได้:

git reset --hard HEAD^

หรือแม้กระทั่งHEAD^^การย้อนคืนสิ่งที่กระทำย้อนกลับ คุณสามารถให้การอ้างอิง SHA เต็มรูปแบบได้ตลอดเวลาหากคุณไม่แน่ใจว่าควรย้อนกลับไปกี่ก้าว

ในกรณีที่ท่านมีปัญหาและสาขาหลักของคุณไม่ได้มีการเปลี่ยนแปลงในระบบใด ๆ origin/masterคุณสามารถตั้งค่าใหม่


5
คำตอบที่ดีที่สุด IMHO รวม OP ของตัวเอง (สมมติว่ามีเพียง 1 ขั้นตอนในการเปลี่ยนกลับซึ่งดูเหมือนจะเป็นกรณีใน Q) รวมถึงทางลัดของ randomguy3 (ซึ่งทำงานเมื่อ "สาขาหลักของคุณไม่มีการเปลี่ยนแปลงในท้องถิ่น ")
inger

4
คุณแสดงความคิดเห็น @Inger และ @Konstantin ทำไม? คุณมาที่นี่หลังจากคำตอบของฉันถูกสร้างขึ้นและมันถูกต้องมากขึ้น แค่ขึ้นไปบน HEAD หนึ่งก้าวก็มักจะผิดและคุณต้องนับว่าคุณต้องไปไกลแค่ไหน Git ได้ตั้งไว้ORIG_HEADสำหรับคุณแล้วทำไมไม่ใช้มันล่ะ
odinho - Velmont

มันจะรีเซ็ตการเปลี่ยนแปลงในเครื่องด้วยหรือไม่ #PleaseUpdate
CoDe

สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันการรีเซ็ตหัวแบบที่เหมาะสมกว่าคำตอบครึ่งหนึ่งที่นี่
Varda Elentári

HEAD ^ เท่ากับกระทำก่อนหน้า HEAD หรือไม่ และ ^^ ก่อนหน้านี้สองคอมมิท? การเดาว่าสิ่งนี้จะไม่ทำงานเมื่อมีการรวมการส่งต่อที่รวดเร็วใช่ไหม
Marcus Leon

87

เมื่อเร็ว ๆ นี้ฉันใช้git reflogเพื่อช่วยในเรื่องนี้ ส่วนใหญ่จะใช้งานได้ก็ต่อเมื่อมีการรวมเพียงเกิดขึ้นและมันอยู่ในเครื่องของคุณ

git reflog อาจส่งคืนสิ่งที่ชอบ:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

บรรทัดแรกระบุว่ามีการผสานเกิดขึ้น บรรทัดที่ 2 คือเวลาก่อนการผสานของฉัน ฉันเพียงแค่git reset --hard 43b6032บังคับให้สาขานี้ติดตามจากก่อนการรวมและดำเนินการต่อ


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

51

ด้วย Git ที่ทันสมัยคุณสามารถ:

git merge --abort

ไวยากรณ์ที่เก่ากว่า:

git reset --merge

โรงเรียนเก่า:

git reset --hard

แต่ที่จริงแล้วมันก็คุ้มค่าที่จะสังเกตเห็นว่าgit merge --abortเทียบเท่ากับgit reset --mergeที่MERGE_HEADมีอยู่ในปัจจุบันเท่านั้น สามารถอ่านได้ในวิธีใช้ Git สำหรับคำสั่งผสาน

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

หลังจากที่มีการผสานล้มเหลวเมื่อไม่มีMERGE_HEADการผสานล้มเหลวสามารถยกเลิกได้ด้วยgit reset --mergeแต่ไม่จำเป็นต้องมีgit merge --abort, ดังนั้นพวกเขาจะไม่เพียง แต่ไวยากรณ์เก่าและใหม่สำหรับสิ่งเดียวกัน

โดยส่วนตัวแล้วฉันพบว่าgit reset --mergeมีประสิทธิภาพและมีประโยชน์มากขึ้นในการทำงานประจำวันดังนั้นฉันจึงมักใช้


ทำงานได้ดีสำหรับฉัน โพสต์อื่น ๆ บอกว่ามันซับซ้อนมาก แต่ก็ทำในสิ่งที่คาดหวัง ฉันคิดว่ามันใช้งานได้เพียงเพราะมีความขัดแย้งซึ่งไม่สามารถตอบคำถามเดิมได้
Jeremy

คำตอบนี้ไม่ได้มุ่งเน้นไปที่สถานการณ์ของ OP และทำให้บริบทสำคัญ
Ben Wheeler

37

ตกลงคำตอบที่คนอื่น ๆ ให้ที่นี่ให้ฉันสนิท แต่ก็ไม่ได้ผล นี่คือสิ่งที่ฉันทำ

ทำสิ่งนี้ ...

git reset --hard HEAD^
git status

... ให้ฉันสถานะต่อไปนี้

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

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

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

เมื่อถึงจุดนี้ฉันเห็นข้อความสถานะเปลี่ยนไปดังนั้นฉันจึงลองทำgit pullและดูเหมือนจะใช้งานได้:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

เรื่องสั้นยาวสั้นคำสั่งของฉันลงมาที่:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull

19
หรือคุณอาจจะเคยใช้HEAD^^^^
hasen

17
อาจจะรีเซ็ตเป็นorigin/master;)
hasen

23

คุณสามารถใช้git reflogเพื่อค้นหาเช็คเอาต์ก่อนหน้า บางครั้งเป็นสถานะที่ดีที่คุณต้องการกลับไป

รูปธรรม

$ git reflog
$ git reset --hard HEAD@{0}

1
ขอบคุณ! คุณบันทึกงานของฉันครึ่งวัน อย่างไรก็ตามฉันไม่สามารถออกจากโหมด reflog ด้วยคำสั่งใด ๆ
Katarzyna

1
@Katarzyna ใช้ปุ่ม "q" เพื่อออกจาก reflog
Amjed Baig

21

หากคุณอยู่ระหว่างการรวมคุณสามารถยกเลิกได้เสมอ git merge --abort


2
ขอบคุณครับและฉันกำลังจะทำสิ่งที่น่ากลัวคำตอบที่ถูกต้อง โชคดีที่ฉันเลื่อนลง ฉันแค่ต้องการลบหัวผสาน
Nyuu

15

ฉันสามารถแก้ไขปัญหานี้ด้วยคำสั่งเดียวที่ไม่เกี่ยวข้องกับการค้นหารหัสการกระทำ

git reset --hard remotes/origin/HEAD

คำตอบที่ยอมรับนั้นใช้ไม่ได้สำหรับฉัน แต่คำสั่งนี้ได้ผลลัพธ์ที่ฉันต้องการ


แน่นอน! รีเซ็ตการเปลี่ยนแปลงของคุณเป็น HEAD ของสาขา! ไม่ทำทีละคน
Carlos Zinato

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

@MattPengelly วิธีนี้ส่วนใหญ่จะไม่มีเอกสารและมักจะใช้งานได้หากสาขาของคุณซิงค์กับสาขาระยะไกลก่อนที่จะทำการผสาน เป็นเวลาหลายเดือนแล้วที่สาขาของคุณซิงค์กับสาขาระยะไกล?
Ralph Ritoch

@ MattPengelly มันยังขึ้นอยู่กับว่าสาขาใดที่ HEAD ชี้ไป ฉันใช้ gitflow กับหนึ่งในโครงการของฉันและแม้ว่าฉันจะอยู่ในสาขาที่พัฒนาแล้วรีโมต / แหล่งกำเนิด / หัวก็จะชี้ไปที่แหล่งกำเนิด / ต้นแบบดังนั้นหากฉันต้องการยกเลิกการรวมฉันอาจต้องรีเซ็ตรีโมต / ที่มา / พัฒนา
Ralph Ritoch

14

หากคุณยังไม่ได้ส่งมอบคุณสามารถใช้งานได้เท่านั้น

$ git checkout -f

มันจะยกเลิกการรวม (และทุกอย่างที่คุณทำ)


พยายามทำสิ่งนี้และเพิ่มจำนวนการผูกมัดที่สาขาในพื้นที่ของฉันล่วงหน้า
barclay

14

หากตอบคำถามนี้ยังต้องการเปลี่ยนกลับเพื่อให้ตรงกับที่มา การค้นคว้าเพิ่มเติมพบว่ามีresetคำสั่งสำหรับสิ่งนั้น:

git reset --hard @{u}

หมายเหตุ: มีการจดชวเลข@{u} origin/master(และแน่นอนคุณต้องใช้ที่เก็บข้อมูลระยะไกลเพื่อให้สิ่งนี้ทำงานได้)


14

คุณต้องเปลี่ยน HEAD ของคุณไม่ใช่ของคุณแน่นอน แต่ git HEAD ....

HEADดังนั้นก่อนที่จะตอบให้เพิ่มพื้นหลังบางอธิบายสิ่งที่เป็นแบบนี้

First of all what is HEAD?

HEADเป็นเพียงการอ้างอิงถึงการกระทำปัจจุบัน (ล่าสุด) ในสาขาปัจจุบัน
สามารถมีได้เพียงครั้งเดียวHEADในเวลาที่กำหนด (ไม่รวมgit worktree)

เนื้อหาของHEADถูกเก็บไว้ภายใน.git/HEADและประกอบด้วย 40 ไบต์ SHA-1 ของการกระทำปัจจุบัน


detached HEAD

หากคุณไม่ได้อยู่บนล่าสุดกระทำ - ความหมายที่จะชี้ไปก่อนกระทำในประวัติศาสตร์ที่เรียกว่าHEADdetached HEAD

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

บนบรรทัดคำสั่งจะมีลักษณะเช่นนี้ - SHA-1 แทนชื่อสาขาเนื่องจากHEADไม่ได้ชี้ไปที่ปลายของสาขาปัจจุบัน

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

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

ตัวเลือกบางอย่างเกี่ยวกับวิธีการกู้คืนจาก HEAD เดี่ยว:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

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

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

คุณสามารถใช้reflogเช่นกัน
git reflogจะแสดงการเปลี่ยนแปลงใด ๆ ที่มีการปรับปรุงHEADและการตรวจสอบรายการ reflog ที่ต้องการจะตั้งค่าHEADกลับไปที่การกระทำนี้

ทุกครั้งที่มีการแก้ไข HEAD จะมีรายการใหม่ใน reflog

git reflog
git checkout HEAD@{...}

สิ่งนี้จะนำคุณกลับไปสู่การกระทำที่คุณต้องการ

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


git reset --hard <commit_id>

"ย้าย" HEAD ของคุณกลับไปยังการกระทำที่ต้องการ

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • หมายเหตุ: ( ตั้งแต่ Git 2.7 )
    คุณสามารถใช้งานได้git rebase --no-autostashเช่นกัน

git revert <sha-1>

"เลิกทำ" ช่วงที่กำหนดหรือกระทำ
คำสั่งรีเซ็ตจะ "เลิกทำ" การเปลี่ยนแปลงใด ๆ ที่ทำในการส่งที่กำหนด
การคอมมิทใหม่ด้วยแพทช์การเลิกทำจะถูกส่งไปในขณะที่การคอมมิชชันดั้งเดิมจะยังคงอยู่ในประวัติศาสตร์เช่นกัน

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

คีมานี้แสดงให้เห็นว่าคำสั่งใดทำอะไร
ในขณะที่คุณสามารถดูมีการปรับเปลี่ยนreset && checkoutHEAD

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


นี่คือสมบัติ 🐱‍👤🐱‍👤🐱‍👤
Jawand Singh

12

คำตอบที่ง่ายที่สุดคือคำตอบที่ได้รับจาก odinho - Velmont

ก่อนอื่นเลย git reset --merge ORIG_HEAD

สำหรับผู้ที่ต้องการรีเซ็ตหลังจากการเปลี่ยนแปลงถูกผลักให้ทำเช่นนี้ (เพราะนี่เป็นโพสต์แรกที่เห็นสำหรับคำถามใด ๆ ที่ผสานการรีเซ็ต git)

git push origin HEAD --force

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


10

เพียงเพื่อตัวเลือกพิเศษในการดูฉันได้รับส่วนใหญ่ตามรูปแบบการแตกสาขาที่อธิบายไว้ที่นี่: http://nvie.com/posts/a-successful-git-branching-model/และได้รับการผสานกับ--no-ff(ไม่ กรอไปข้างหน้า)

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

ดังนั้นเพื่อคืนความมุ่งมั่นทั้งหมดฉันแค่ต้องการอันใดอันหนึ่งgit reset --hard HEAD^และมันหวนคืนการผสานทั้งหมด เนื่องจากการผสานไม่ได้ส่งต่ออย่างรวดเร็วการผสานจึงเป็นบล็อกและย้อนกลับไปหนึ่งขั้นตอนคือ "ไม่รวมสาขา"


10

คุณสามารถใช้เพียงสองคำสั่งเพื่อยกเลิกการผสานหรือเริ่มต้นใหม่โดยกระทำที่เฉพาะเจาะจง:

  1. git reset --hard commitHash (คุณควรใช้การคอมมิตที่คุณต้องการรีสตาร์ทเช่น 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (การส่งสาขาหลักในพื้นที่ใหม่ไปยังจุดเริ่มต้น / ต้นแบบ)

ขอให้โชคดีและไปข้างหน้า!


10

สามารถทำได้หลายวิธี

1) ยกเลิกการรวม

หากคุณอยู่ในระหว่างการรวมที่ไม่ดี (ทำผิดกับสาขาที่ไม่ถูกต้อง) และต้องการหลีกเลี่ยงการรวมเพื่อกลับไปที่สาขาล่าสุดดังต่อไปนี้:

git merge --abort

2) รีเซ็ต HEAD เป็นสาขาระยะไกล

หากคุณกำลังทำงานจากสาขาการพัฒนาระยะไกลคุณสามารถรีเซ็ต HEAD เป็นการกระทำล่าสุดในสาขาระยะไกลดังต่อไปนี้:

git reset --hard origin/develop

3) ลบสาขาปัจจุบันและชำระเงินอีกครั้งจากที่เก็บระยะไกล

เมื่อพิจารณาแล้วคุณกำลังทำงานเพื่อพัฒนาสาขาใน repo ท้องถิ่นที่ซิงค์กับสาขาระยะไกล / พัฒนาคุณสามารถทำดังต่อไปนี้:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop

ว่า "1) Abort Merge" นั้นสวยพอสมควร Upvoting
CodeToLife

1
ระวัง! git merge --abort "สามารถทำงานได้หลังจากการผสานได้ทำให้เกิดข้อขัดแย้ง git merge --abort จะยกเลิกกระบวนการผสานและพยายามสร้างสถานะ pre-merge ใหม่"
Pedro García Medina

8

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

ตัวอย่างเช่นฉันบังเอิญรวมสาขาพัฒนาเข้ากับปริญญาโทและต้องการยกเลิกสิ่งนั้น ใช้ขั้นตอนต่อไปนี้:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! อาจารย์อยู่ในขั้นตอนเดียวกับที่มาและสถานะที่ผิดพลาดของคุณถูกลบ


1
หมายเหตุ: สิ่งนี้ไม่เพียง แต่เลิกทำการผสาน แต่ยังรวมถึงการกระทำในท้องถิ่นที่เกิดขึ้นตั้งแต่การพุชครั้งล่าสุด
Martijn Heemels

4

หากคุณต้องการโซลูชันบรรทัดคำสั่งฉันขอแนะนำให้ไปกับคำตอบของ MBO

หากคุณเป็นมือใหม่คุณอาจชอบวิธีกราฟิก:

  1. Kick off gitk(จากบรรทัดคำสั่งหรือคลิกขวาในเบราเซอร์ไฟล์ถ้าคุณมีนั้น)
  2. คุณสามารถสังเกตเห็นการรวมการกระทำที่นั่น - โหนดแรกจากด้านบนที่มีผู้ปกครองสองคน
  3. ตามลิงค์ไปยังผู้ปกครองคนแรก / ซ้าย (คนที่อยู่ในสาขาปัจจุบันของคุณก่อนการรวมมักเป็นสีแดงสำหรับฉัน)
  4. ในการกระทำที่เลือกคลิกขวา "รีเซ็ตสาขาไปที่นี่" เลือกฮาร์ดรีเซ็ตที่นั่น

4

กลยุทธ์:สร้างสาขาใหม่จากทุกสิ่งที่ดี

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

สารละลาย:

สมมติว่าคุณต้องการรวมdevเข้าfeature-1ด้วยกัน

  1. ค้นหาการแก้ไขที่คุณต้องการรับการผสาน:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. ลองดู (ย้อนเวลากลับไป):

    git checkout e5f6g7h8
    
  3. สร้างสาขาใหม่จากที่นั่นและลองดู:

    git checkout -b feature-1
    

ตอนนี้คุณสามารถเริ่มการผสานของคุณใหม่:

  1. ผสาน: git merge dev

  2. แก้ไขข้อขัดแย้งการรวมของคุณ

  3. Commit: git commit

  4. เมื่อคุณพอใจกับผลลัพธ์ให้ลบสาขาเก่า: git branch --delete feature-1


2

เพียงแค่สร้างสาขาใหม่จากนั้นเลือกเชอร์รี่ที่ผูกพันกับมัน

ประหยัดและง่ายขึ้นจากนั้นรีเซ็ตการอธิบายในคำตอบมากมายข้างต้น


1
ฉันเห็นด้วยกับข้อเสนอแนะนี้โดยเฉพาะถ้าคุณไม่พอใจกับคำสั่ง git ทั้งหมด สิ่งนี้อาจช้าลงด้วย "ความเหน็ดเหนื่อย" ที่มากขึ้น แต่ถ้ามันไม่ได้เกิดขึ้นมากและคุณกังวลเกี่ยวกับการสูญเสียงานของคุณมันก็คุ้มค่ากับความพยายาม
เกร็ก

1

ฉันคิดว่าคุณสามารถทำได้git rebase -i [hash] [branch_name] โดย[hash]ใช้แฮชตัวระบุที่อยู่ด้านหลังคุณต้องการย้อนกลับบวกหนึ่ง (หรือหลายคอมมิชชันที่คุณต้องการย้อนกลับ) แล้วลบบรรทัดสำหรับคอมมิทในตัวแก้ไขที่คุณไม่ต้องการอีกต่อไป . บันทึกไฟล์ ทางออก อธิษฐาน และมันควรจะกรอ คุณอาจต้องทำgit reset --hardแต่มันควรจะดีในจุดนี้ คุณยังสามารถใช้วิธีนี้เพื่อดึงการคอมมิทเฉพาะออกจากสแต็กถ้าคุณไม่ต้องการเก็บไว้ในประวัติของคุณ แต่มันสามารถทำให้ที่เก็บของคุณอยู่ในสถานะที่คุณอาจไม่ต้องการ


1

หากคุณส่งจดหมายเวียน:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard

1
  1. ขั้นแรกตรวจสอบให้แน่ใจว่าคุณได้ทำทุกสิ่ง

  2. จากนั้นรีเซ็ตที่เก็บของคุณเป็นสถานะการทำงานก่อนหน้า:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    หรือการใช้--hard( สิ่งนี้จะลบการเปลี่ยนแปลงในพื้นที่ทั้งหมดไม่ใช่การเปลี่ยนแปลงที่ยอมรับ! ):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    ใช้แฮชที่อยู่ก่อนหน้าการคอมมิชชันที่คุณทำผิดไป

  3. ตรวจสอบความมุ่งมั่นที่คุณต้องการมอบให้อีกครั้งบนเวอร์ชันที่ถูกต้องก่อนหน้านี้โดย:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. ใช้ความมุ่งมั่นของคุณด้านบนของรุ่นที่ถูกต้องของพื้นที่เก็บข้อมูลของคุณโดย:

    • โดยใช้ cherry-pick (การเปลี่ยนแปลงที่นำเสนอโดยบางคอมมิทที่มีอยู่)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • หรือโดยเชอร์รี่เลือกช่วงของการกระทำโดย:

      • ก่อนตรวจสอบการเปลี่ยนแปลงที่ถูกต้องก่อนที่จะผสาน:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • ก่อนตรวจสอบการเปลี่ยนแปลงที่ถูกต้องก่อนที่จะผสาน:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        เมื่อนี่คือช่วงของการคอมมิตที่ถูกต้องซึ่งคุณได้ทำไว้ (ไม่รวมการรวมที่ผูกมัดไว้ผิด)



0

git reset --hard HEAD@{1}ถ้าคุณสังเกตเห็นว่าคุณจะต้องย้อนกลับไปในทันทีหลังจากที่การผสานและคุณยังไม่ได้ทำอะไรอย่างอื่นหลังจากความพยายามผสานคุณก็สามารถออกคำสั่งนี้:

โดยพื้นฐานแล้วการผสานของคุณshaจะถูกชี้ไปที่HEAD@{0}หากไม่มีอะไรเกิดขึ้นหลังจากการรวมและHEAD@{1}จะเป็นจุดก่อนหน้าก่อนการผสาน


0

โอกาสที่ง่ายที่สุดที่ง่ายที่สุดนั้นง่ายกว่าที่กล่าวไว้ทั้งหมด:

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


0

git reset --hard <branch_name>ในกรณีนี้คุณจะต้องการรีเซ็ตสาขาของคุณด้วย หากคุณต้องการบันทึกการเปลี่ยนแปลงของคุณก่อน reseting git checkout <branch_name>พวกเขาจะแน่ใจว่าการสร้างสาขาใหม่และ

คุณสามารถรีเซ็ตสถานะเป็นคอมมิชชันเฉพาะด้วยgit reset --hard <commit_id>เช่นกัน

หากมีการผลักดันการเปลี่ยนแปลงคุณสามารถใช้git revert <branch_name>แทน อย่าลืมตรวจสอบวิธีการใช้git revert และ git checkoutในสถานการณ์อื่น ๆ ด้วย

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