จะเกิดอะไรขึ้นกับคอมมิตคอมมิตที่สร้างขึ้นในสถานะ HEAD แยก


142

นี่คือสิ่งที่เกิดขึ้น:

ฉันมีสาขา A. ในสาขา AI ยอมรับการเปลี่ยนแปลงมากมาย ฉันไม่พอใจกับรหัสดังนั้นฉันจึงตรวจสอบการกระทำก่อนหน้านี้ในสาขา A จากนั้นฉันจึงทำการเปลี่ยนแปลงอีกหลายครั้งและทำการเปลี่ยนแปลงในสาขา A ตอนนี้ฉันไม่พบการคอมมิตนี้ที่ไหนเลย ฉันทำรหัสนี้หายหรือไม่?


เมื่อคุณพูดว่า "ฉันตรวจสอบการคอมมิตก่อนหน้าในสาขา A" คุณหมายถึง "ฉันรีเซ็ตสาขา A เป็นคอมมิตก่อนหน้านี้" ใช่หรือไม่ นั่นคือคุณเป็นจริงgit resetมากกว่าgit checkout?
CB Bailey

ไม่ฉันใช้การชำระเงิน reflog ทำงาน
Mausimo

หากคุณใช้การชำระเงินคุณจะอยู่ในห้องเดี่ยวHEADและสาขา A จะยังคงอยู่กับการกระทำก่อนหน้านี้ คุณรันคำสั่งอะไรกันแน่?
CB Bailey

1
ฉันใช้ SourceTree GIT GUI บน OSX Lion ฉันอยู่ที่สาขา A และดำเนินการชำระเงินของการกระทำก่อนหน้านี้ในสาขา A จากนั้นฉันได้ทำการเปลี่ยนแปลงรหัสและตกลง (สาขา A) ฉันเชื่อว่าฉันมี HEAD ที่แยกออกมา
Mausimo

ตกลงผมคิดว่าผมสับสนเมื่อคุณบอกว่าคุณมุ่งมั่นที่เปลี่ยนแปลงพวงมากขึ้นในสาขา
CB Bailey

คำตอบ:


194

คอมมิตเก่ายังอยู่ใน reflog

git reflog

ซึ่งจะแสดงรายการคอมมิตและคอมมิต "สูญหาย" ควรอยู่ในนั้น คุณสามารถทำให้เป็นสาขาใหม่ได้ ตัวอย่างเช่นหาก SHA-1 คือ ba5a739 คุณสามารถสร้างสาขาใหม่ชื่อ "สาขาใหม่" ที่คอมมิตเก่าด้วย:

git branch new-branch ba5a739

โปรดทราบว่าการคอมมิต "สูญหาย" จะถูกลบออกเมื่อฐานข้อมูลถูกตัดออก


16
ใช้git cherry-pick [SHA]เพื่อย้ายการกระทำไปยังสาขาที่มีอยู่ในกรณีที่คุณตั้งใจกระทำโดยไม่ได้ตั้งใจในขณะที่อยู่ในสถานะหัวหน้าแยก
Jan Aagaard Meier

3
หรือคุณสามารถเปลี่ยนไปใช้สาขาที่มีอยู่แล้วทำ "git merge HEAD @ {n}" n ที่สอดคล้องกับคอมมิต "สูญหาย" ที่แสดงอยู่ใน reflog
eaykin

คุณรู้หรือไม่ว่าpruneจะลบคอมมิตที่แยกออกจากกันที่ถูกอ้างอิงในข้อความคอมมิตหรือไม่ หรือว่าทำให้เข้าถึงได้ ?
Kamafeather

@Kamafeather: ฉันไม่คิดว่าจะทำให้พวกเขาเข้าถึงได้
Dietrich Epp

ฉันคิดอย่างนั้น ฉัน ... มันคงเป็นคุณสมบัติที่ดีในการอ้างอิงต้นไม้ที่เขียนซ้ำ / ที่หายไป (สำหรับคำขอดึงที่ตรวจสอบแล้วในกรณีของฉัน) [บางทีฉันควรเปิดคำขอคุณสมบัติ!] ยังไงก็ขอบคุณนะ.
Kamafeather

66

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

  1. ค้นหาแฮช SHA-1 ของคอมมิตที่คุณทำในสถานะ HEAD แยกด้วย

    git reflog
    
  2. จากนั้นดำเนินการโดยแฮชคอมมิตทั้งหมดเรียงลำดับจากเก่าที่สุดไปยังล่าสุด:

    git cherry-pick <hash1> <hash2> <hash3> ...
    

    ตัวอย่างเช่นถ้าฉันมีเพียงตัวเดียวโดยกำหนดในรูปแบบแฮชสั้น "7 อักขระแรก":

    git cherry-pick a21d053
    

สิ่งนี้จะสร้างการคอมมิตใหม่ให้กับสาขาปัจจุบันของคุณหนึ่งคอมมิตต่อแฮช HEAD - คอมมิตที่แยกออกจากกันที่คุณพูดถึงในคำสั่ง นอกจากนี้ยังรับช่วงข้อความคอมมิตเดิม


12

คุณอาจพบว่าหลงทาง (ห้อย) กระทำด้วยคำสั่งต่อไปนี้:

git fsck --lost-found

หมายเหตุถ้าหัวปัจจุบันของคุณห้อยคอมมิตจะไม่อยู่ในรายการว่าสูญหาย

คุณสามารถดูข้อมูลเพิ่มเติมได้ที่git-fsck (1) หน้าคู่มือ

จากนั้นคุณสามารถสร้างสาขาในการกระทำที่สูญหายนั้น:

git branch new-branch ba5a739

ครั้งแรกฉันใช้คำสั่ง "git reflog" จากนั้น "git branch new-branch ba5a739" สำหรับโมดูลย่อยมันใช้งานได้
ondermerol

7

Git parlance สำหรับสถานะของไดเร็กทอรีการทำงานของคุณคือ " detached HEAD " ที่นี่เป็นอีกสถานที่หนึ่งที่git reflogทำให้ประหยัด

$ git reflog
0b40dd6 HEAD@{0}: commit: my commit on detached HEAD
...

หากฉันพยายามชำระเงินสาขาอื่น git-1.7.5.1 จะให้คำแนะนำที่เป็นประโยชน์

$ git หลักการชำระเงิน
คำเตือน: คุณกำลังทิ้ง 1 คอมมิตไว้ข้างหลังไม่ได้เชื่อมต่อกับ
สาขาใดก็ได้ของคุณ:

  0b40dd6 การกระทำของฉันใน HEAD ที่แยกออกมา

หากคุณต้องการเก็บไว้โดยการสร้างสาขาใหม่นี่อาจเป็นช่วงเวลาที่ดี
โดยใช้:

 สาขา git new_branch_name 0b40dd65c06bb215327863c2ca10fdb4f904215b

เปลี่ยนเป็นสาขา "หลัก"

6

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


4

ทำตามขั้นตอนเหล่านี้เพื่อเชื่อมโยงหัวแยกของคุณกลับไปที่ git repo

  1. git checkout "your branch with path but without remote name"

เช่นถ้าชื่อระยะไกลเป็นที่มาและชื่อสาขาจะถูกbugfix/somebranchใช้git checkout bugfix/somebranch

  1. git reflog รับคอมมิต SHA ที่แสดงรายการจากรายการคอมมิตของสาขาแยก

  2. git cherry-pick "commit hash1" "commit hash2" "commit hash3"

  3. git push

ทุกชุด!!


2

ใน Sourcetree ฉันพบว่า git reflog ไม่ทำงานดังนั้นฉันจึงหาวิธีทำโดยใช้ GUI

ขั้นแรกให้ลองค้นหาการกระทำที่ "สูญหาย" โดยค้นหาข้อความในประวัติคำสั่ง (มุมมอง: แสดงเอาต์พุตคำสั่ง) หวังว่าจะอยู่ในคำสั่ง "Switching Branch" หลังจากการคอมมิตที่คุณทำหายและคุณจะเห็นคอมเมนต์คอมมิตพร้อมรหัสคอมมิต 1234567

นำ Commit ID นั้นไปยังขั้นตอนถัดไป

กดปุ่ม "Branch" ในแถบเครื่องมือด้านบนและคุณจะได้รับกล่องโต้ตอบ "New Branch" ซึ่งคุณสามารถระบุการกระทำบางอย่างได้ ใส่รหัสคอมมิตนั้นระบุชื่อสาขาใหม่กดสร้างสาขาแล้วคุณจะได้สาขาใหม่พร้อมกับคอมมิตที่หายไป!

สิ่งนี้นำงานที่หายไปกลับคืนมาให้ฉัน!

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