คำแนะนำในการแก้ไขข้อผิดพลาดด้วย Git (ตอนที่ 2)

เผยแพร่แล้ว: 2022-03-10
สรุปด่วน ↬ ข้อผิดพลาด เหล่าวายร้ายที่โหดร้ายเหล่านี้ไม่ได้หยุดอยู่ที่โลกที่สวยงามของการพัฒนาซอฟต์แวร์ แต่ถึงแม้เราจะหลีกเลี่ยงไม่ได้ แต่เราเรียนรู้ที่จะเลิกทำสิ่งเหล่านั้นได้! บทความนี้จะแสดงเครื่องมือที่เหมาะสมสำหรับการทำงานประจำวันของคุณด้วย Git คุณอาจต้องการตรวจสอบบทความแรกของซีรีส์ด้วย

ในภาคที่ 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 ดำเนินการสำคัญทั้งหมดในพื้นที่เก็บข้อมูลของเรา
โปรโตคอล Reflog ของ Git ดำเนินการสำคัญทั้งหมดในที่เก็บข้อมูลในเครื่องของเรา (ตัวอย่างขนาดใหญ่)

ต่อไปนี้คือความคิดเห็นบางส่วนที่จะช่วยให้คุณเข้าใจผลลัพธ์ที่ได้:

  • ก่อนอื่น คุณต้องรู้ว่า Reflog เรียงลำดับรายการตามลำดับเวลา: รายการใหม่ล่าสุดจะอยู่ด้านบนสุดของรายการ
  • รายการบนสุด (และใหม่ล่าสุด) คือคำสั่ง git checkout ที่เราดำเนินการก่อนที่จะลบสาขา มันถูกบันทึกไว้ที่นี่ใน Reflog เพราะเป็นหนึ่งใน "การเคลื่อนไหวของตัวชี้ HEAD" ที่ Reflog บันทึกตามหน้าที่
  • เพื่อแก้ไขข้อผิดพลาดร้ายแรงของเรา เราสามารถกลับไปที่สถานะ ก่อนหน้า นั้น - ซึ่งได้รับการบันทึกไว้อย่างชัดเจนและชัดเจนใน Reflog!

ลองทำสิ่งนี้โดยสร้างสาขาใหม่ (ด้วยชื่อสาขาที่ "สูญหาย") ซึ่งเริ่มต้นที่สถานะ "ก่อน" แฮช SHA-1:

 $ git branch feature/login 776f8ca

แล้วโว้ย! คุณจะดีใจที่เห็นว่าตอนนี้เราได้ฟื้นฟูสาขาที่ดูเหมือนหายไปแล้ว!

หากคุณใช้ Git บนเดสก์ท็อป GUI เช่น “Tower” คุณสามารถใช้ช็อตคัทที่ดีได้ เพียงกด CMD + Z บนแป้นพิมพ์ของคุณเพื่อเลิกทำคำสั่งสุดท้าย แม้ว่าคุณจะเพิ่งลบสาขาออกไปอย่างรุนแรง!

GUI บนเดสก์ท็อปเช่น Tower สามารถทำให้กระบวนการแก้ไขข้อผิดพลาดง่ายขึ้น
เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

ย้ายพันธสัญญาไปสาขาอื่น

ในหลายทีม มีข้อตกลงที่จะไม่คอมมิตกับแบรนช์ที่ใช้เวลานานเช่น 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 ในคำสั่ง:

แสดงช่วงของการกระทำที่เราเลือกสำหรับการแก้ไขในเซสชัน Rebase เชิงโต้ตอบของเรา
ช่วงของการกระทำที่เราเลือกสำหรับการแก้ไขในเซสชัน Rebase เชิงโต้ตอบของเรา (ตัวอย่างขนาดใหญ่)

นี่เป็นสิ่งสำคัญที่คุณ จะต้องไม่ ทำตามแรงกระตุ้นแรกของคุณ: ในขั้นตอนนี้ เรายัง ไม่ได้ แก้ไขข้อความยืนยัน แต่เราเพียงบอก Git ว่าเราต้องการทำอะไรกับการ กระทำ ใด ค่อนข้างสะดวก มีรายการคำหลักของการดำเนินการระบุไว้ในความคิดเห็นที่ด้านล่างของหน้าต่างนี้ สำหรับกรณีของเรา เราทำเครื่องหมายบรรทัดที่ 1 ด้วย reword (ดังนั้นจึงแทนที่การ pick มาตรฐาน )

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

นี่คือกระบวนการทั้งหมดโดยสรุปสำหรับคุณ:

ใช้ Interactive Rebase เพื่อแก้ไขข้อความของคอมมิตเก่า ตั้งแต่ต้นจนจบ

การแก้ไขข้อผูกมัดที่หัก (อย่างสง่างามมาก)

สุดท้าย เราจะมาดูการแก้ไข Swiss Army fixup ของเครื่องมือการเลิกทำ พูดง่ายๆ ก็คือ มันช่วยให้คุณแก้ไขการคอมมิตที่เสียหาย/ไม่สมบูรณ์/ไม่ถูกต้องหลังจากข้อเท็จจริง เป็นเครื่องมือที่ยอดเยี่ยมด้วยเหตุผลสองประการ:

  1. ไม่สำคัญว่าปัญหาคืออะไร
    คุณอาจลืมเพิ่มไฟล์ ควรลบบางอย่าง ทำการเปลี่ยนแปลงที่ไม่ถูกต้อง หรือเพียงแค่พิมพ์ผิด fixup ทำงานได้ในทุกสถานการณ์เหล่านี้!
  2. มันสง่างามมาก
    ปฏิกิริยาปกติตามสัญชาตญาณของเราต่อจุดบกพร่องในการคอมมิตคือการสร้างคอมมิต ใหม่ ที่แก้ไขปัญหาได้ วิธีการทำงานนี้ แม้จะดูเป็นสัญชาตญาณก็ตาม จะทำให้ประวัติการคอมมิตของคุณดูวุ่นวายในเร็วๆ นี้ คุณมีคอมมิต "ดั้งเดิม" และ "band-aid" เล็กน้อยเหล่านี้คอมมิชชันที่แก้ไขสิ่งที่ผิดพลาดในการคอมมิตดั้งเดิม ประวัติของคุณเต็มไปด้วยวงดนตรีช่วยเหลือเล็กๆ น้อยๆ ที่ไม่มีความหมาย ซึ่งทำให้ยากที่จะเข้าใจว่าเกิดอะไรขึ้นใน codebase ของคุณ
ประวัติการคอมมิตของคุณอาจอ่านยากมากหากคุณแก้ไขข้อผิดพลาดเล็กๆ น้อยๆ อย่างต่อเนื่องด้วยสิ่งที่เรียกว่า band-aid commits
การแก้ไขข้อผิดพลาดเล็กๆ น้อยๆ อย่างต่อเนื่องด้วย "band-aid commit" ทำให้ประวัติการคอมมิตของคุณอ่านยากมาก (ตัวอย่างขนาดใหญ่)

นี่คือที่ fixup ของการแก้ไข มันช่วยให้คุณยังคงทำการแก้ไข band-aid นี้ แต่เวทย์มนตร์มาถึงแล้ว: จากนั้นนำไปใช้กับคอมมิตดั้งเดิมที่เสีย (ซ่อมแซมด้วยวิธีนี้) แล้วทิ้ง band-aid ที่น่าเกลียดทั้งหมด!

Fixup นำการแก้ไขของคุณไปใช้กับการคอมมิตดั้งเดิม จากนั้นจึงกำจัดการคอมมิต Band-aid ฟุ่มเฟือย
Fixup นำการแก้ไขของคุณไปใช้กับการคอมมิตดั้งเดิม จากนั้นจึงกำจัดการคอมมิต 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 ตัวเลือกคืออะไร เราต้องทำงานหนักมาก! ในหน้าต่างตัวแก้ไขที่เปิดขึ้นตอนนี้ ทุกอย่างพร้อมแล้วสำหรับเรา:

หน้าต่างเซสชัน Rebase แบบโต้ตอบ
หน้าต่างเซสชัน Rebase แบบโต้ตอบ (ตัวอย่างขนาดใหญ่)

ขอบคุณตัวเลือก --autosquash Git ได้ทำหน้าที่ของเราอย่างหนัก:

  1. มันทำเครื่องหมายวงดนตรีช่วยเหลือเล็กน้อยของเราด้วยคำ fixup ดำเนินการแก้ไข ด้วยวิธีนี้ Git จะรวมเข้ากับการคอมมิต ด้านบน โดยตรงแล้วละทิ้ง
  2. นอกจากนี้ยังจัดลำดับบรรทัดใหม่ตามลำดับโดยย้าย band-aid commit ของเราโดยตรงด้านล่างการคอมมิทที่เราต้องการแก้ไข (อีกครั้ง: การ fixup ทำงานโดยการรวมการคอมมิตที่ทำเครื่องหมายไว้กับรายการ ด้านบน !)

กล่าวโดยย่อ: ไม่มีอะไรทำสำหรับเรานอกจากปิดหน้าต่าง!

มาดูผลลัพธ์สุดท้ายกัน

  • คอมมิตที่พังก่อนหน้านี้ได้รับการแก้ไขแล้ว: ตอนนี้มีการเปลี่ยนแปลงที่เราเตรียมในการคอมมิต band-aid
  • ตัวช่วยแบนด์วิดธ์ที่น่าเกลียดถูกละทิ้ง: ประวัติการคอมมิตนั้นสะอาดและอ่านง่าย - ราวกับว่าไม่มีข้อผิดพลาดเกิดขึ้นเลย
ตัวอย่างของประวัติการคอมมิตที่ชัดเจน
ผลลัพธ์ที่ได้หลังจากใช้เครื่องมือแก้ไข: ประวัติการคอมมิตใหม่ทั้งหมด! (ตัวอย่างขนาดใหญ่)

การรู้วิธีแก้ไขข้อผิดพลาดเป็นพลังวิเศษ

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

หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการเลิกทำผิดพลาดกับ Git ฉันสามารถแนะนำ "ชุดปฐมพยาบาลสำหรับ Git" ฟรี ซึ่งเป็นชุดวิดีโอสั้น ๆ เกี่ยวกับหัวข้อนี้

ขอให้สนุกกับการทำผิดพลาด และแน่นอน เลิกทำได้อย่างง่ายดาย!