Git| Single Branch in the context of ODDS

Jirawat Kurakhan
odds.team
Published in
3 min readMay 13, 2024
Photo by Yancy Min on Unsplash

Git เป็นหนึ่งในเครื่องมือประเภท Version Control ยอดนิยม ที่ช่วยให้พวกเราชาว Developer ทำงานร่วมกันได้ง่ายขึ้น สามารถติดตามสอดส่องดูการแก้ไขในแต่ละครั้งได้ ตรงตามประเภทของการใช้งานที่ถูกจัดหมวดหมู่ไว้

เจ้า Git นี้เองหลักๆ ก็ช่วยตามที่บอกด้านบนนี่แหละ สิ่งที่ทำให้มันกลายมาเป็นประเด็นพูดคุยกันในครั้งนี้คือ วิธีการใช้งานของมันที่มีมากมาย ไม่มีตายตัว ขึ้นอยู่กับการทำงาน ไปจนถึงวัฒนธรรมของทีมนั้นๆ ครับ ซึ่งไม่ว่าคุณจะอยู่ลัทธิการใช้งาน Git แบบไหน ทำงานด้วยวิธีแบบไหนอยู่ อยากให้ลองมาอ่าน นิยามการใช้งาน Git ที่ Scope เล็กลงหน่อยของ ODDS ดูครับ

ที่ ODDS นั้นเราทำงานอยู่บนความหลากหลาย มีลูกค้าหลากหลายประเภทที่เราเข้าไปทำงานด้วย ซึ่งก็มีอยู่บ่อยครั้งเลยครับ ที่เราได้ซึมซับวัฒนธรรมการทำงานของทางลูกค้ามา และนำมาแชร์หรือบอกต่อให้กับคนภายใน ODDS ให้ได้มา discuss กันครับ ซึ่ง 1 ในนั้นคือเรื่องของ การทำงานบน Git แบบ Single Branch

ทำไมถึงมันถูกพูดถึงขึ้นมาได้นะ มันน่าจะตรงตัวเลยไม่ใช่หรอ ?

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

แต่ถ้าเราจะทำให้มันเท่ากันทุกคนล่ะ ? ควรจะ focusในเรื่องไหนบ้างนะ

งั้นเราเริ่มกันไปทีละข้อนะครับ

ข้อแรก : มี Branch หลัก (long-lived branch) ได้กี่ Branch

อ้าว ทำ Single Branch ก็ควรเป็น Branch เดียวสิ ไม่เห็นคิดยากเลย

แต่เรามีทีมที่ทำงานบน branch develop จบ sprint เอาเข้า uat ถ้าหากจะ deploy production ให้เอาเข้า branch main แบบนี้นับเป็น single branch มั้ยนะ ?

หลังจากพูดคุยกันอยู่นาน เราก็ได้ข้อสรุปมาดังนี้ครับ

  • Branch หลักของการทำงาน จะมี 1 Branch เท่านั้น
  • ในกรณีมี 3 branch ที่ยกตัวอย่างไปก่อนหน้า หากเรา maintain ให้มี history หรือ version เดียวกันตลอดเวลา (develop > uat > main) จะถือว่า branch ทำงานหลักเราคือ develop และถือเป็น single branch ส่วน branch นอกจาก develop จะถือว่าเป็นของที่เอาไว้ checkpoint ในแต่ละรอบ sprint ซึ่งเป็น constants ไม่ใช่ variable
  • กรณีที่เกิด hotfix ให้กลับมา maintain uat และ develop ตามไปด้วย

ข้อสอง : แตก Branch ได้หรือไม่ ?

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

  • ทีมที่ทำงานบน develop branch ตรงๆ โดยในการทำงานทุกครั้งพวกเขาจะต้อง push และ pull rebase บ่อยๆ
  • ทีมที่แตก feature branch ออกมา แล้ว merge / rebase กลับเข้าไปที่ develop

หาก apply กับนิยามข้อแรก กรณีแรกชัดเจนในตัวของมันเองอยู่แล้ว ส่วนกรณีที่ 2 นี่เราต้องทำให้มันเล็กลงกว่านี้ครับ ด้วยคำถามที่ว่า

Branch ที่คุณแตกออกมาทำเป็น feature นี่อะ มีอายุนานเท่าไหร่ ?

เราได้คำตอบมาหลากหลายมาก ตั้งแต่ 5 นาทีไปจนถึงจบ sprint กันเลยทีเดียว เราใช้เวลาซักพักเพื่อให้ generate ชุดคำตอบที่มากเพียงพอที่จะเห็นแนวโน้ม ตัดเรื่องขนาดของทีมและองค์กรออกไป ทำให้เราได้ข้อสรุปว่า ควรจะมีอายุนานที่สุดคือ 1 วัน

คำถามต่อมาคือ แล้วอะไรที่ทำให้เราได้ตัวเลขนี้ออกมา ?

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

และหากเกินกว่า 1 วันไปแล้ว คุณต้องยอมรับแล้วล่ะ ว่าความเสี่ยงของการเอาเข้ามันมีมากยิ่งขึ้น ยิ่ง branch หลักไปไกลเท่าไหร่ cost ของการ integration ก็จะเริ่มสูงขึ้นไปเป็นเท่าตัว เพื่อให้เราคล่องตัวมากที่สุด จึงกำหนดให้ 1 วัน มีช่วงเวลาตั้งแต่ Standup Meeting จนถึง Standup Meeting ครั้งต่อไป

ข้อสาม : merge หรือ rebase

หากอ่านมาถึงตรงนี้แล้ว ต้องบอกเลยว่าที่ผ่านมาผมใช้คำว่า `เอาเข้า <branch>` หมดเลย เพราะคำว่าเอาเข้าไปเนี่ยมันมีหลายแบบ (ซึ่งที่เราเอามา discuss กัน มีแค่ 2 แบบ) แล้วแต่ละแบบ ต่างกันยังไงนะ ?

https://github.com/ByteByteGoHq/system-design-101/blob/main/images/git-merge-git-rebase.jpeg
  • Merge เป็นรูปแบบของการรวมของกัน ซึ่งจะมี commit เพิ่มเติมมา 1 commit ซึ่งเกิดจากการนำของล่าสุดของ feature branch มารวมกับของล่าสุดใน main branch เกิดเป็น merge commit ขึ้นมาครับ หากดูใน history ของ Git จะเห็นเป็นการทำงานขนานที่กันเกิดขึ้น และสุดท้ายก็จะมีปมหนึ่งเกิดขึ้นมาที่เกิดจากการรวมกันนั่นเองครับ
  • Rebase เป็นรูปแบบของการปรับฐาน (base) โดยการขยับฐานจากฐานที่เก่า กลายเป็นฐานที่ใหม่ (B -> D) ครับ และของที่ทำใน feature branch จะต้องพยายามทำให้ทั้ง 3 commit ที่เกิดขึ้นมา เข้ากันได้กับของล่าสุดบน main ให้ได้ กรณีนี้เองจะไม่เกิด commit ใหม่ขึ้นมา และเมื่อดูใน history ของ Git เอง ก็จะเห็นว่า ในเส้นสองเส้นที่ขนานกันอยู่จะมีเพียงเส้นเดียวที่มีจุด (commit) เกิดขึ้น ซึ่งต่างจากการ merge ที่ทั้งสองเส้นที่ขนานกันจะมีจุดทั้งสองเส้นก่อนจะ merge เข้าหากัน

ซึ่งในครั้งนี้ เราเองก็เลือกให้เอาเข้าแบบ rebase ด้วยเหตุผลที่ว่า

ลูกค้าจ้างเรามาเขียน code ไม่ได้จ้างเรามาแก้ conflict ที่เกิดขึ้นจากการ merge code ในทุกครั้งที่เรากด merge มีโอกาสไม่น้อยเลยที่เดียวที่ code ของเพื่อนร่วมทีมและเราจะหายไป ในทุกครั้งที่เรากระโดดเข้าไปแก้ conflict เราต่างก็ใช้เวลา ใช้ความเสี่ยง และใช้ cost เพื่อให้ code ของเราและเพื่อนร่วมทีมทำงานอย่างที่ควรจะเป็น ซึ่งเมื่อเทียบกับการ rebase แล้ว เวลาและ cost ที่ใช้จะลดลงไปมากๆ ครับ เนื่องจากเราจะเห็นทุกการเปลี่ยนแปลงในแต่ละ commit ที่เกิดขึ้นระหว่างการ rebase ทำให้เรารู้ได้ว่า ในแต่ละ commit นั้นเกิดขึ้นมาด้วยสาเหตุใด เพราะเราต้องคอยปรับ history ให้กลายเป็นเส้นตรงนั่นเอง

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

ข้อที่สี่ : Branch หลักต้องเป็น releasable software ตลอดเวลา และหากมันพัง ต้องให้ความสำคัญในการแก้ไขให้เร็วที่สุด เพื่อให้เราส่งมอบของได้อย่างต่อเนื่องและมีประสิทธิภาพอยู่ตลอดเวลา (Continuous Delivery : CD)

ซึ่งข้อนี้เป็นข้อที่สำคัญที่สุดที่เรายกให้มาเป็นอันดับ 1 แม้จะมาเป็นข้อสุดท้ายก็ตาม

  • สำหรับทีมที่ทำงานบน develop branch ตรง พวกเขาจะมีความเชื่อใจกันสูงมาก พวกเขาต่างยึดมั่นใน Test ทุกรูปแบบที่เขาเขียนขึ้น หากมันพังด้วยสถานการณ์ที่ไม่คาดคิด พวกเขาทุกคนมีสิทธิ์ในการแก้ไข แม้ว่าจะไม่ใช่จุดที่ตนเองเขียนก็ตาม
  • สำหรับทีมที่ทำงานแบบแตก feature branch พวกเขาแต่ละคนจะต้องรับผิดชอบในสิ่งที่ตัวเองเขียนอย่างดีที่สุด สิ่งที่พวกเขาทำออกมาจะมีระเบียบแบบแผนชัดเจน ก่อนที่พวกเขาจะเอาเข้า branch หลัก จะต้องตรวจทานอย่างมั่นใจ ไม่ว่าจะด้วยวิธีการ Code Review หรือแบบใดก็ตามแต่ เพื่อให้มันยังคง concept ของการทำงานได้ต่อไป

จบแล้วกับการนิยามแบบของเราชาว ODDS เกี่ยวกับการทำงานแบบ Single Branch ครับ หากผู้อ่านตามเราไม่ทัน ทางผมเองก็ได้สรุปประเด็นการคุยไว้ประมาณนี้ครับ

  1. มี Branch ทำงานหลักได้เพียง 1 Branch เท่านั้น
  2. สามารถแตก branch การทำงานย่อยได้ แต่ต้องมีอายุไม่เกิน 1 วัน
  3. ใช้วิธีการรวม branch แบบ rebase
  4. Branch ทำงานหลักจะต้องเป็น releasable software ตลอดเวลา

อย่างไรก็ตาม นี่เป็นเพียงนิยามของพวกเราใน Open space ที่พูดคุย ณ ตอนนั้นครับ ต้องบอกว่าสิ่งนี้ไม่ใช่ของที่ทุกทีมภายใน ODDS ต้องนำไปปรับใช้ทันที มันเป็นเพียง-`คำนิยาม` เท่านั้น เพื่อให้ทุกคนเข้าใจได้ตรงกัน ส่วนในเรื่องของการปรับใช้ ทางผมเองคิดว่า สมาชิกในทีมนั่นแหละครับ ที่สามารถบอกได้ว่าเขาสบายใจในการทำงานแบบใด และปรับใช้ยังไงได้บ้างครับ

ขอบคุณผู้อ่านที่อ่านมาถึงตรงนี้ครับ หวังว่าผู้อ่านจะได้รับประโยชน์บ้างไม่มากก็น้อย หากมีข้อสงสัยหรือคำถามที่อยากให้เราไปพูดคุยเพิ่มเติม สามารถมาชวนพวกเราคุยได้เลยนะครับ 🙇🏻‍♂️

Reference:

--

--