Git branch: สัญชาตญาณกับความเป็นจริง
(jvns.ca)- หลายคนมองว่าวิธีการทำงานของ Git branch นั้นไม่ค่อยเป็นไปตามสัญชาตญาณ
- อธิบายความแตกต่างระหว่างโมเดลเชิงสัญชาตญาณที่คนทั่วไปมีต่อ Git branch กับวิธีที่ branch ถูกแสดงจริง ๆ ภายใน Git
- แสดงให้เห็นว่าโมเดลเชิงสัญชาตญาณกับวิธีการทำงานจริงของ Git นั้นเกี่ยวข้องกันอย่างใกล้ชิดมาก
- พูดถึงข้อจำกัดของโมเดลเชิงสัญชาตญาณและเหตุผลที่มันอาจก่อปัญหาได้
โมเดล branch แบบสัญชาตญาณ
- หลายคนเปรียบ branch ว่าเป็นเหมือน 'กิ่งของต้นแอปเปิล'
- ใน Git branch ไม่มีแนวคิดเรื่อง 'พ่อแม่' และไม่เหมือนกับการคิดว่ามันแตกออกมาจาก
main
ใน Git branch คือประวัติทั้งหมด
- ใน Git branch ไม่ได้เป็นแค่ commit ที่แยกออกมา แต่รวมประวัติทั้งหมดของ commit ก่อนหน้าด้วย
- ผ่าน repository ตัวอย่าง แสดงให้เห็นว่า
mainและmybranchต่างก็มี 4 commit ทั้งคู่
branch ถูกเก็บเป็น commit ID
- ภายใน Git branch ถูกเก็บเป็นไฟล์ข้อความขนาดเล็กที่มี commit ID อยู่ข้างใน
- commit ล่าสุดของแต่ละ branch จะถูกบันทึกไว้ในไฟล์นั้น
- เนื่องจากไม่มีความสัมพันธ์แบบพ่อ-ลูกระหว่าง branch Git จึงไม่รู้ความสัมพันธ์ระหว่าง branch ต่าง ๆ
สัญชาตญาณของผู้คนมักไม่ได้ผิดนัก
- การบอกว่าสัญชาตญาณของผู้คนเกี่ยวกับ Git นั้น 'ผิด' อาจเป็นเรื่องที่ไร้สาระอยู่บ้าง
- แม้โมเดลที่ 'ผิด' ก็ยังมีประโยชน์ได้จริง
rebase ใช้แนวคิด branch แบบ 'สัญชาตญาณ'
- rebase จะนำเฉพาะ commit ของ branch แบบ 'สัญชาตญาณ' ไปปรับใช้ใหม่บน
main - ผลลัพธ์ของ rebase สอดคล้องกับโมเดลเชิงสัญชาตญาณ
merge ก็ใช้แนวคิด branch แบบ 'สัญชาตญาณ' เช่นกัน
- merge ไม่ได้คัดลอก commit แต่ต้องอาศัย base commit ที่ใช้ร่วมกัน
- merge base จะช่วยหา commit ที่ branch แบบสัญชาตญาณแยกตัวออกมา
GitHub Pull Request ก็ใช้แนวคิดเชิงสัญชาตญาณ
- เมื่อสร้าง Pull Request เพื่อ merge
mybranchเข้าmainบน GitHub ระบบจะแสดงเฉพาะ commit ของ branch แบบสัญชาตญาณเท่านั้น
สัญชาตญาณนั้นดี แต่ก็มีข้อจำกัด
- คำนิยาม branch แบบสัญชาตญาณเข้ากันได้ดีกับการทำงานจริงใน Git แต่ Git ไม่สามารถรับรู้ branch ที่แยกมาจาก
mainได้แตกต่างเป็นพิเศษ
trunk กับ branch ที่แตกออกมา
- ผู้คนรับรู้
mainและmybranchว่าแตกต่างกัน และสิ่งนี้ส่งผลต่อวิธีการใช้งาน Git - Git ไม่ได้แยกแยะว่า branch ใดเป็น 'กิ่งที่แตกออกมา' จากอีก branch หนึ่ง
Git สามารถ rebase แบบ 'ย้อนทาง' ได้
- เพราะ Git ไม่ได้บอกว่า branch ใดเป็น 'กิ่งที่แตกออกมา' จากอีก branch หนึ่ง ผู้ใช้จึงต้องรู้เองว่าเมื่อไรควร rebase branch ไหน
- ทั้ง
git rebase mainและการ rebase ย้อนทางอย่างgit rebase mybranchต่างก็ทำได้ เช่นเดียวกับ merge
การไม่มีโครงสร้างลำดับชั้นระหว่าง Git branch ก็ค่อนข้างแปลก
- การที่บอกว่า branch
mainไม่ได้พิเศษ เกิดจาก Git ไม่สามารถรับรู้ความสัมพันธ์ระหว่าง branch ได้ - ระหว่าง branch ต่าง ๆ มีความสัมพันธ์กันอยู่ แต่ git ไม่รู้อะไรเลย
UI ของ Git branch ก็แปลกเหมือนกัน
- เวลาที่อยากดูเฉพาะ commit ที่ 'แตกออกมา' วิธีใช้
git logและgit diffนั้นแตกต่างกัน
บน GitHub default branch เป็นสิ่งพิเศษ
- GitHub มี 'default branch' ซึ่งมีบทบาทพิเศษ
ความเห็นของ GN⁺
ประเด็นสำคัญที่สุดของบทความนี้คือการเข้าใจความแตกต่างระหว่างความเข้าใจเชิงสัญชาตญาณของผู้คนเกี่ยวกับ Git branch กับวิธีการทำงานจริงของ Git บทความนี้จะช่วยให้วิศวกรซอฟต์แวร์ระดับเริ่มต้นเข้าใจแนวคิดของ Git branch ได้ดีขึ้นและใช้งานได้อย่างมีประสิทธิภาพมากขึ้น การได้เห็นว่าโมเดล branch แบบสัญชาตญาณสอดคล้องกับการทำงานจริงอย่างไร และ Git ไม่ได้จัดการความสัมพันธ์ระหว่าง branch อย่างไรบ้าง เป็นทั้งเรื่องน่าสนใจและมีประโยชน์
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
git reset --hardและgit stashเพื่อจัดการการเปลี่ยนแปลงและพอยน์เตอร์ของบรานช์ในโปรเจกต์ส่วนตัว เพื่อน ๆ มักจะโกรธกันบ่อย ๆ ถ้าต้องยกเลิก merge ที่ผิดพลาด ก็ใช้git reset --hard <병합 전 마지막 커밋>และถ้าต้องการนำการแก้ไขเล็ก ๆ บน local branch ไปใช้กับ main branch ก็ใช้git stashจากนั้น checkout ไปที่ main branch แล้วใช้git stash applygit addและgit commitอยู่แล้ว บทเรียนนี้ช่วยให้เรียนรู้ไปพร้อมกับการมองเห็นภาพของบรานช์ได้git merge my-branchคือการ merge my-branch เข้ากับบรานช์ปัจจุบัน และgit rebase my-branchคือการ rebase บรานช์ปัจจุบันขึ้นไปบน my-branchmainก็จะสะดวกกว่าgit range-diffก็ต้องคำนึงถึงฐานนี้ด้วย เครื่องมือนี้เปรียบเทียบสองช่วง เช่นmain..previousและmain..current