ฉันจะกู้คืนคอมมิชชันที่สูญหายไปใน Git ได้อย่างไร?


258

ก่อนอื่นได้รับ "สาขาของคุณล้ำหน้ากว่าต้นทาง / หลักด้วย 3 คอมมิชชัน" จากนั้นแอพของฉันกลับไปเป็นครั้งก่อนโดยมีการเปลี่ยนแปลงก่อนหน้านี้

ฉันจะได้สิ่งที่ฉันใช้ไปในช่วง 11 ชั่วโมงที่ผ่านมาได้อย่างไร


คำตอบ:


587

git reflogเป็นเพื่อนของคุณ. ค้นหากระทำที่คุณต้องการจะอยู่ในรายการที่และคุณสามารถตั้งค่าให้กับมัน (ตัวอย่างเช่น: git reset --hard e870e41)

(หากคุณไม่ได้กระทำการเปลี่ยนแปลงของคุณ ... คุณอาจมีปัญหา - ทำ แต่เนิ่น ๆ และทำบ่อย ๆ !)


5
git log HEAD@{1}ลองดูที่ git reset HEAD@{1}ถ้ารูปลักษณ์ที่เหมือนชุดขวาของกระทำแล้วคุณสามารถ
แอมเบอร์

4
เฉพาะในกรณีที่รหัสที่มีการจัดฉาก (ใช้คอมไพล์เพิ่ม) git fsck --lost-foundพวกเขาจะถูกเก็บไว้ในคอมไพล์และสามารถพบได้กลับมาอย่างง่ายดายโดยใช้คำสั่งเช่น
Landys

2
การส่งคำสั่งโดยไม่ตั้งใจฉันควรเก็บไว้เมื่อทำการรีบูต สิ่งนี้ช่วยฉันทั้งหมดจากการทำงานซ้ำสองสามชั่วโมง
josephting

27
สิ่งนี้ช่วยชีวิตฉันได้
Lutaaya Huzaifah Idris

6
สิ่งนี้ช่วยรักษาสติของฉัน: D
Frank Fajardo

117

ก่อนที่จะตอบลองเพิ่มพื้นหลังอธิบายว่านี่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 a 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

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


2
คุณเป็นฮีโร่ครับ
dylanh724

4
นั่นเพิ่งช่วยฉันทำงานหลายชั่วโมง ฉันใช้ "git reflog --date = iso" เพื่อดูวันที่ / เวลาสำหรับแต่ละรายการเนื่องจากฉันไม่สามารถบอกได้อย่างแน่นอนว่าไม่มีการประทับเวลา
MetalMikester

1
สำหรับฉันในgit reset --hard <commit_id>การลบHEADทำงาน! +1 สำหรับการแสดงกราฟิก !!
reverie_ss

เพียงพูดถึง: ถ้าคุณรู้ชื่อสาขา: git reflog <branchname>จะมีประโยชน์มากเพราะคุณเห็นการเปลี่ยนแปลงของสาขาเดียว
Markus Schreiber

35

อีกวิธีในการไปยังการคอมมิตที่ถูกลบคือการใช้git fsckคำสั่ง

git fsck --lost-found

สิ่งนี้จะให้ผลลัพธ์ที่บรรทัดสุดท้าย:

dangling commit xyz

เราสามารถตรวจสอบได้ว่ามันเป็นการกระทำแบบเดียวกันกับที่ใช้reflogในคำตอบอื่น ๆ ตอนนี้เราสามารถทำgit merge

git merge xyz

หมายเหตุ:
เราไม่สามารถรับการส่งคืนด้วยfsckถ้าเราได้รันgit gcคำสั่งแล้วซึ่งจะลบการอ้างอิงไปยังการผูกห้อย


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