ก่อนอื่นมาอธิบายให้ชัดเจนว่า HEAD คืออะไรและหมายความว่าอย่างไรเมื่อถอดออก
HEAD เป็นชื่อที่เป็นสัญลักษณ์สำหรับการกระทำที่ได้ชำระเงินแล้ว เมื่อ HEAD ไม่ได้ถูกแยกออก (สถานการณ์“ ปกติ” 1 : คุณมีสาขาที่เช็คเอาท์แล้ว) HEAD จะชี้ไปที่“ ref” ของสาขาและชี้ไปที่การกระทำ หัวจึง "แนบ" กับสาขา เมื่อคุณทำการคอมมิชชันใหม่สาขาที่ HEAD ชี้ไปจะถูกอัพเดตเพื่อชี้ไปที่การคอมมิทใหม่ HEAD ติดตามโดยอัตโนมัติเนื่องจากเพิ่งชี้ไปที่สาขา
git symbolic-ref HEAD
ถัวrefs/heads/master
เฉลี่ยที่สาขาที่ชื่อว่า“ ต้นแบบ” ได้รับการชำระ
git rev-parse refs/heads/master
อัตราผลตอบแทน17a02998078923f2d62811326d130de991d1a95a
ที่กระทำคือเคล็ดลับปัจจุบันหรือ "หัว" ของสาขาหลัก
git rev-parse HEAD
ยังให้ผล17a02998078923f2d62811326d130de991d1a95a
นี่คือความหมายของการเป็น“ การอ้างอิงเชิงสัญลักษณ์” มันชี้ไปที่วัตถุผ่านการอ้างอิงอื่น
(แต่เดิม refs สัญลักษณ์ถูกนำไปใช้เป็นลิงค์สัญลักษณ์ แต่ภายหลังเปลี่ยนเป็นไฟล์ธรรมดาที่มีการตีความเพิ่มเติมเพื่อให้สามารถใช้บนแพลตฟอร์มที่ไม่มี symlink ได้)
เรามีHEAD
→การrefs/heads/master
→การ17a02998078923f2d62811326d130de991d1a95a
เมื่อ HEAD ถูกถอดออกมันจะชี้ไปยังการกระทำโดยตรงแทนที่จะชี้ไปทางหนึ่งผ่านทางสาขา คุณสามารถนึกถึงเฮดเดอร์เดี่ยวที่อยู่ในสาขาที่ไม่มีชื่อ
git symbolic-ref HEAD
ล้มเหลวด้วย fatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
ถัวเฉลี่ย17a02998078923f2d62811326d130de991d1a95a
เนื่องจากมันไม่ใช่การอ้างอิงเชิงสัญลักษณ์มันจะต้องชี้ไปที่การยอมรับโดยตรง
เรามีHEAD
→17a02998078923f2d62811326d130de991d1a95a
สิ่งสำคัญที่ต้องจำไว้กับ HEAD เดี่ยวคือถ้าการกระทำนั้นชี้ไปที่ไม่ได้รับการอ้างอิง (ไม่มีผู้อ้างอิงคนอื่นสามารถเข้าถึงได้) จากนั้นมันจะกลายเป็น "ห้อย" เมื่อคุณชำระเงินกระทำ ในที่สุดการกระทำที่ห้อยต่องแต่งดังกล่าวจะถูกตัดผ่านกระบวนการรวบรวมขยะ (โดยค่าเริ่มต้นจะถูกเก็บไว้อย่างน้อย 2 สัปดาห์และอาจถูกเก็บไว้นานขึ้นโดยอ้างอิงจากการอ้างอิงของ HEAD)
1
การทำงานแบบ“ ปกติ” อย่างสมบูรณ์แบบด้วยหัวเดี่ยวคุณต้องติดตามสิ่งที่คุณกำลังทำเพื่อหลีกเลี่ยงการตกปลาที่หลุดออกจากการอ้างอิง
ขั้นตอนกลางของการรีบูตแบบโต้ตอบจะทำโดยใช้ HEAD ที่แยกออกมา หากคุณเสร็จสิ้นการดำเนินการรีบูตแบบเต็มมันจะอัปเดตสาขาเดิมของคุณด้วยผลลัพธ์สะสมของการดำเนินการรีบูตและติดตั้ง HEAD กลับไปที่สาขาเดิม ฉันเดาว่าคุณไม่เคยทำกระบวนการรีบูตให้เสร็จสมบูรณ์ สิ่งนี้จะทำให้คุณมี HEAD เดี่ยว ๆ ที่ชี้ไปที่การคอมมิทที่ถูกประมวลผลล่าสุดโดยการดำเนินการรีบูต
ในการกู้คืนจากสถานการณ์ของคุณคุณควรสร้างสาขาที่ชี้ไปที่การกระทำที่ชี้ไปในขณะนี้โดยหัวหน้าของคุณ:
git branch temp
git checkout temp
(ทั้งสองคำสั่งนี้สามารถย่อเป็นgit checkout -b temp
)
สิ่งนี้จะแนบหัวของคุณไปยังtemp
สาขาใหม่
ถัดไปคุณควรเปรียบเทียบการกระทำปัจจุบัน (และประวัติ) กับสาขาปกติที่คุณคาดว่าจะทำงาน:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
(คุณอาจต้องการทดลองใช้ตัวเลือกบันทึก: เพิ่ม-p
ออกไป--pretty=…
เพื่อดูข้อความบันทึกทั้งหมด ฯลฯ )
หากtemp
สาขาใหม่ของคุณดูดีคุณอาจต้องการอัปเดต (เช่น) master
เพื่อชี้ไปที่:
git branch -f master temp
git checkout master
(ทั้งสองคำสั่งนี้สามารถย่อเป็นgit checkout -B master temp
)
จากนั้นคุณสามารถลบสาขาชั่วคราว:
git branch -d temp
ในที่สุดคุณอาจต้องการที่จะผลักดันประวัติศาสตร์ที่ตีพิมพ์ซ้ำ:
git push origin master
คุณอาจจำเป็นต้องเพิ่ม--force
ที่ส่วนท้ายของคำสั่งนี้เพื่อผลักดันหากสาขาระยะไกลไม่สามารถ“ ส่งต่ออย่างรวดเร็ว” ไปยังการส่งมอบใหม่ (เช่นคุณทิ้งหรือเขียนใหม่การกระทำที่มีอยู่หรือเขียนประวัติเล็กน้อย)
หากคุณอยู่ระหว่างการดำเนินการรีบูตคุณควรทำความสะอาด คุณสามารถตรวจสอบว่ามี rebase .git/rebase-merge/
อยู่ในขั้นตอนโดยการมองหาไดเรกทอรี คุณสามารถล้างข้อมูล rebase ที่กำลังดำเนินการได้ด้วยตนเองโดยเพียงแค่ลบไดเรกทอรีนั้น (เช่นหากคุณไม่จำวัตถุประสงค์และบริบทของการดำเนินการ rebase ที่ใช้งานอยู่) โดยปกติแล้วคุณจะใช้งานgit rebase --abort
แต่นั่นเป็นการตั้งค่าพิเศษบางอย่างที่คุณอาจต้องการหลีกเลี่ยง (จะย้าย HEAD กลับไปที่สาขาดั้งเดิมและรีเซ็ตกลับไปเป็นการกระทำดั้งเดิมซึ่งจะยกเลิกการทำงานบางอย่างที่เราทำด้านบน)