คำแนะนำในการแก้ไขข้อผิดพลาดด้วย Git (ตอนที่ 2)
เผยแพร่แล้ว: 2022-03-10ในภาคที่ 2 ของซีรีส์เรื่อง “Undoing Mistakes with Git” เราจะกลับมามองดูอันตรายอีกครั้งอย่างกล้าหาญ: ฉันได้เตรียมสถานการณ์วันโลกาวินาศใหม่ 4 สถานการณ์ รวมถึงวิธีที่ชาญฉลาดในการช่วยชีวิตเราด้วย! แต่ก่อนที่เราจะดำดิ่งลงไป: ดูที่บทความก่อนหน้าเกี่ยวกับ Git เพื่อดูวิธีการช่วยเหลือตนเองที่จะช่วยคุณแก้ไขความผิดพลาดด้วย Git!
ไปกันเถอะ!
การกู้คืนสาขาที่ถูกลบโดยใช้Reflog
คุณเคยลบสาขาและหลังจากนั้นไม่นานคุณก็รู้ว่าไม่ควรมีหรือไม่? ในกรณีที่คุณไม่รู้ความรู้สึกนี้ บอกเลยว่ามันไม่ใช่ความรู้สึกที่ดี ความเศร้าและความโกรธปะปนเกิดขึ้นกับคุณ ในขณะที่คุณคิดถึงการทำงานหนักทั้งหมดที่นำไปสู่ความมุ่งมั่นของสาขานั้น รหัสอันมีค่าทั้งหมดที่คุณสูญเสียไปในตอนนี้
โชคดีที่มีวิธีนำแบรนช์นั้นกลับมาจากความตาย ด้วยความช่วยเหลือของเครื่องมือ Git ชื่อ “Reflog” เราได้ใช้เครื่องมือนี้ในส่วนแรกของซีรีส์ของเรา แต่นี่เป็นการทบทวนเล็กน้อย: Reflog เป็นเหมือนวารสารที่ Git บันทึกทุกการเคลื่อนไหวของตัวชี้ HEAD ในที่เก็บในเครื่องของคุณ กล่าวอีกนัยหนึ่งที่ไม่น่าสนใจ: ทุกครั้งที่คุณชำระเงิน คอมมิต รวม รีเบส เลือกเชอร์รี่ และอื่นๆ รายการบันทึกประจำวันจะถูกสร้างขึ้น สิ่งนี้ทำให้ Reflog เป็นเครือข่ายความปลอดภัยที่สมบูรณ์แบบเมื่อมีสิ่งผิดปกติ!
ลองมาดูตัวอย่างที่เป็นรูปธรรม:
$ git branch * feature/login master
เราจะเห็นได้ว่าขณะนี้เรา feature/login
เช็คเอาท์ สมมติว่านี่คือสาขาที่เราจะลบ (โดยไม่ตั้งใจ) ก่อนที่เราจะทำอย่างนั้นได้ เราต้องเปลี่ยนไปใช้สาขาอื่นเพราะเราไม่สามารถลบสาขา HEAD ปัจจุบันของเราได้!
$ git checkout master $ git branch -d feature/login
ฟีเจอร์ที่มีคุณค่าของเราได้หายไปแล้ว - และฉันจะให้เวลาคุณสักครู่เพื่อ (a) เข้าใจถึงความสำคัญของความผิดพลาดของเรา และ (b) ไว้ทุกข์เล็กน้อย เช็ดน้ำตาเสร็จต้องหาทางเอากิ่งนี้กลับคืนมา! มาเปิด Reflog กันเถอะ (เพียงแค่พิมพ์ git reflog
) และดูว่ามันมีอะไรให้เราบ้าง:
ต่อไปนี้คือความคิดเห็นบางส่วนที่จะช่วยให้คุณเข้าใจผลลัพธ์ที่ได้:
- ก่อนอื่น คุณต้องรู้ว่า Reflog เรียงลำดับรายการตามลำดับเวลา: รายการใหม่ล่าสุดจะอยู่ด้านบนสุดของรายการ
- รายการบนสุด (และใหม่ล่าสุด) คือคำสั่ง
git checkout
ที่เราดำเนินการก่อนที่จะลบสาขา มันถูกบันทึกไว้ที่นี่ใน Reflog เพราะเป็นหนึ่งใน "การเคลื่อนไหวของตัวชี้ HEAD" ที่ Reflog บันทึกตามหน้าที่ - เพื่อแก้ไขข้อผิดพลาดร้ายแรงของเรา เราสามารถกลับไปที่สถานะ ก่อนหน้า นั้น - ซึ่งได้รับการบันทึกไว้อย่างชัดเจนและชัดเจนใน Reflog!
ลองทำสิ่งนี้โดยสร้างสาขาใหม่ (ด้วยชื่อสาขาที่ "สูญหาย") ซึ่งเริ่มต้นที่สถานะ "ก่อน" แฮช SHA-1:
$ git branch feature/login 776f8ca
แล้วโว้ย! คุณจะดีใจที่เห็นว่าตอนนี้เราได้ฟื้นฟูสาขาที่ดูเหมือนหายไปแล้ว!
หากคุณใช้ Git บนเดสก์ท็อป GUI เช่น “Tower” คุณสามารถใช้ช็อตคัทที่ดีได้ เพียงกด CMD + Z บนแป้นพิมพ์ของคุณเพื่อเลิกทำคำสั่งสุดท้าย แม้ว่าคุณจะเพิ่งลบสาขาออกไปอย่างรุนแรง!
ย้ายพันธสัญญาไปสาขาอื่น
ในหลายทีม มีข้อตกลงที่จะไม่คอมมิตกับแบรนช์ที่ใช้เวลานานเช่น main
หรือ develop
: สาขาเช่นนี้ ควรได้รับการคอมมิตใหม่ผ่านการผสานรวมเท่านั้น (เช่น การผสานหรือการรีเบส) และแน่นอนว่าความผิดพลาดเป็นสิ่งที่หลีกเลี่ยงไม่ได้ บางครั้งเราก็ลืมและทุ่มเทให้กับสาขาเหล่านี้ แล้วเราจะทำความสะอาดระเบียบที่เราทำได้อย่างไร?
โชคดีที่ปัญหาประเภทนี้สามารถแก้ไขได้ง่าย พับแขนเสื้อแล้วไปทำงานกัน
ขั้นตอนแรกคือการสลับไปยังสาขาปลายทางที่ถูกต้อง จากนั้นย้ายการคอมมิตโดยใช้คำสั่ง cherry-pick
มากเกินไป:
$ git checkout feature/login $ git cherry-pick 776f8caf
ตอนนี้คุณจะมีคอมมิตบนแบรนช์ที่ต้องการ ซึ่งมันควรจะเป็นตั้งแต่แรก สุดยอด!
แต่ยังมีอีกสิ่งหนึ่งที่ต้องทำ: เราต้องทำความสะอาดกิ่งไม้ที่มัน บังเอิญ ตกลงไปในตอนแรก! คำสั่ง cherry-pick
นั้นสร้างสำเนาของการคอมมิท — แต่ต้นฉบับยังคงอยู่ในสาขาที่ดำเนินมายาวนานของเรา:
ซึ่งหมายความว่าเราต้องเปลี่ยนกลับไปใช้แบรนช์ที่ใช้เวลานานและใช้การ git reset
เพื่อลบออก:
$ git checkout main $ git reset --hard HEAD~1
อย่างที่คุณเห็น เราใช้คำสั่ง git reset
เพื่อลบคอมมิตที่ผิดพลาด พารามิเตอร์ HEAD~1
บอก Git ให้ "ย้อนกลับ 1 การแก้ไขหลัง HEAD" โดยจะลบค่าสูงสุด (และในกรณีของเรา: ไม่ต้องการ) คอมมิตจากประวัติของสาขานั้นอย่างมีประสิทธิภาพ
และแน่นอน: ภาระผูกพันมาถึงจุดที่ควรจะเป็นตั้งแต่แรก แล้ว และ สาขาที่ดำเนินมายาวนานของเราก็สะอาดสะอ้าน — ราวกับว่าความผิดพลาดของเราไม่เคยเกิดขึ้น!
แก้ไขข้อความของพันธสัญญาเดิม
ง่ายเกินไปที่จะลักลอบพิมพ์ผิดในข้อความยืนยัน — และค้นพบในภายหลังเท่านั้น ในกรณีเช่นนี้ ตัวเลือก --amend
เก่าที่ดีของ git commit
ไม่สามารถใช้เพื่อแก้ไขปัญหานี้ได้ เพราะมันใช้ได้เฉพาะกับการคอมมิตครั้งสุดท้ายเท่านั้น ในการแก้ไขคอมมิตที่เก่ากว่านั้น เราต้องใช้เครื่องมือ Git ที่เรียกว่า “Interactive Rebase”
อันดับแรก เราต้องบอก Interactive Rebase ว่าส่วนใดของประวัติการคอมมิตที่เราต้องการแก้ไข สิ่งนี้ทำได้โดยป้อนค่าคอมมิชชันแฮช: parent คอมมิทของอันที่เราต้องการจัดการ
$ git rebase -i 6bcf266b
หน้าต่างตัวแก้ไขจะเปิดขึ้น ประกอบด้วยรายการของการคอมมิตทั้งหมด หลังจาก ที่เราจัดเตรียมไว้เป็นพื้นฐานสำหรับ Interactive Rebase ในคำสั่ง:
นี่เป็นสิ่งสำคัญที่คุณ จะต้องไม่ ทำตามแรงกระตุ้นแรกของคุณ: ในขั้นตอนนี้ เรายัง ไม่ได้ แก้ไขข้อความยืนยัน แต่เราเพียงบอก Git ว่าเราต้องการทำอะไรกับการ กระทำ ใด ค่อนข้างสะดวก มีรายการคำหลักของการดำเนินการระบุไว้ในความคิดเห็นที่ด้านล่างของหน้าต่างนี้ สำหรับกรณีของเรา เราทำเครื่องหมายบรรทัดที่ 1 ด้วย reword
(ดังนั้นจึงแทนที่การ pick
มาตรฐาน )
สิ่งที่ต้องทำในขั้นตอนนี้คือบันทึกและปิดหน้าต่างตัวแก้ไข ในทางกลับกัน หน้าต่างตัวแก้ไขใหม่จะเปิดขึ้นซึ่งมีข้อความปัจจุบันของการคอมมิตที่เราทำเครื่องหมายไว้ และ ใน ที่สุดก็ถึงเวลาที่เราจะทำการแก้ไขของเรา!
นี่คือกระบวนการทั้งหมดโดยสรุปสำหรับคุณ:
การแก้ไขข้อผูกมัดที่หัก (อย่างสง่างามมาก)
สุดท้าย เราจะมาดูการแก้ไข Swiss Army fixup
ของเครื่องมือการเลิกทำ พูดง่ายๆ ก็คือ มันช่วยให้คุณแก้ไขการคอมมิตที่เสียหาย/ไม่สมบูรณ์/ไม่ถูกต้องหลังจากข้อเท็จจริง เป็นเครื่องมือที่ยอดเยี่ยมด้วยเหตุผลสองประการ:
- ไม่สำคัญว่าปัญหาคืออะไร
คุณอาจลืมเพิ่มไฟล์ ควรลบบางอย่าง ทำการเปลี่ยนแปลงที่ไม่ถูกต้อง หรือเพียงแค่พิมพ์ผิดfixup
ทำงานได้ในทุกสถานการณ์เหล่านี้! - มันสง่างามมาก
ปฏิกิริยาปกติตามสัญชาตญาณของเราต่อจุดบกพร่องในการคอมมิตคือการสร้างคอมมิต ใหม่ ที่แก้ไขปัญหาได้ วิธีการทำงานนี้ แม้จะดูเป็นสัญชาตญาณก็ตาม จะทำให้ประวัติการคอมมิตของคุณดูวุ่นวายในเร็วๆ นี้ คุณมีคอมมิต "ดั้งเดิม" และ "band-aid" เล็กน้อยเหล่านี้คอมมิชชันที่แก้ไขสิ่งที่ผิดพลาดในการคอมมิตดั้งเดิม ประวัติของคุณเต็มไปด้วยวงดนตรีช่วยเหลือเล็กๆ น้อยๆ ที่ไม่มีความหมาย ซึ่งทำให้ยากที่จะเข้าใจว่าเกิดอะไรขึ้นใน codebase ของคุณ
นี่คือที่ fixup
ของการแก้ไข มันช่วยให้คุณยังคงทำการแก้ไข band-aid นี้ แต่เวทย์มนตร์มาถึงแล้ว: จากนั้นนำไปใช้กับคอมมิตดั้งเดิมที่เสีย (ซ่อมแซมด้วยวิธีนี้) แล้วทิ้ง band-aid ที่น่าเกลียดทั้งหมด!
เราสามารถดูตัวอย่างที่ใช้งานได้จริงด้วยกัน! สมมติว่าคอมมิตที่เลือกที่นี่เสีย
สมมติว่าฉัน ได้ เตรียมการเปลี่ยนแปลงในไฟล์ชื่อ error.html
ที่จะแก้ปัญหา นี่คือขั้นตอนแรกที่เราต้องทำ:
$ git add error.html $ git commit --fixup 2b504bee
เรากำลังสร้างคอมมิตใหม่ แต่กำลังบอก Git ว่านี่เป็นคอมมิตพิเศษ: เป็นการแก้ไขคอมมิตแบบเก่าด้วยแฮช SHA-1 ที่ระบุ ( 2b504bee
ในกรณีนี้)
ขั้นตอนที่สอง ตอนนี้ คือการเริ่มเซสชัน Interactive Rebase — เนื่องจาก fixup
เป็นของชุดเครื่องมือขนาดใหญ่ของ Interactive Rebase
$ git rebase -i --autosquash 0023cddd
มีสองสิ่งที่ควรค่าแก่การอธิบายเกี่ยวกับคำสั่งนี้ ประการแรก เหตุใดฉันจึงระบุ 0023cddd
เป็นแฮชการแก้ไขที่นี่ เพราะเราต้องเริ่มเซสชัน Interactive Rebase ที่การคอมมิตระดับบนสุดของเพื่อนที่มีปัญหาของเรา
ประการที่สอง --autosquash
ตัวเลือกคืออะไร เราต้องทำงานหนักมาก! ในหน้าต่างตัวแก้ไขที่เปิดขึ้นตอนนี้ ทุกอย่างพร้อมแล้วสำหรับเรา:
ขอบคุณตัวเลือก --autosquash
Git ได้ทำหน้าที่ของเราอย่างหนัก:
- มันทำเครื่องหมายวงดนตรีช่วยเหลือเล็กน้อยของเราด้วยคำ
fixup
ดำเนินการแก้ไข ด้วยวิธีนี้ Git จะรวมเข้ากับการคอมมิต ด้านบน โดยตรงแล้วละทิ้ง - นอกจากนี้ยังจัดลำดับบรรทัดใหม่ตามลำดับโดยย้าย band-aid commit ของเราโดยตรงด้านล่างการคอมมิทที่เราต้องการแก้ไข (อีกครั้ง: การ
fixup
ทำงานโดยการรวมการคอมมิตที่ทำเครื่องหมายไว้กับรายการ ด้านบน !)
กล่าวโดยย่อ: ไม่มีอะไรทำสำหรับเรานอกจากปิดหน้าต่าง!
มาดูผลลัพธ์สุดท้ายกัน
- คอมมิตที่พังก่อนหน้านี้ได้รับการแก้ไขแล้ว: ตอนนี้มีการเปลี่ยนแปลงที่เราเตรียมในการคอมมิต band-aid
- ตัวช่วยแบนด์วิดธ์ที่น่าเกลียดถูกละทิ้ง: ประวัติการคอมมิตนั้นสะอาดและอ่านง่าย - ราวกับว่าไม่มีข้อผิดพลาดเกิดขึ้นเลย
การรู้วิธีแก้ไขข้อผิดพลาดเป็นพลังวิเศษ
ยินดีด้วย! ตอนนี้คุณสามารถรักษาคอของคุณได้ในสถานการณ์ที่ยากลำบากมากมาย! เราไม่สามารถหลีกเลี่ยงสถานการณ์เหล่านี้ได้อย่างแท้จริง ไม่ว่าเราจะมีประสบการณ์มากแค่ไหนในฐานะนักพัฒนา ความผิดพลาดก็เป็นส่วนหนึ่งของงาน แต่ตอนนี้คุณรู้วิธีจัดการกับมันแล้ว คุณสามารถเผชิญหน้ากับพวกเขาด้วยอัตราการเต้นของหัวใจที่ผ่อนคลาย
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการเลิกทำผิดพลาดกับ Git ฉันสามารถแนะนำ "ชุดปฐมพยาบาลสำหรับ Git" ฟรี ซึ่งเป็นชุดวิดีโอสั้น ๆ เกี่ยวกับหัวข้อนี้
ขอให้สนุกกับการทำผิดพลาด และแน่นอน เลิกทำได้อย่างง่ายดาย!