มาทำความรู้จัก Git Branch
ทำไมเราถึงต้องมาใช้ Git Branch ด้วยมันดียังไง เมื่อบทความที่แล้วได้พูดถึงการทำงานของ git ว่า คำสั่งเบื่องต้นที่ส่วนมากเขาใช้งานใน git ส่วนใหญ่ใช้อะไรในการทำงานบ่าง
แต่ถ้าใครอ่านจบหรือลองเล่นตามบทความแล้ว เอะใจไหมว่าที่จริงตัว git มันออกแบบมาเพื่อทำงานร่วมกันเป็น Team นี้หว่า.. ทำไมไม่เห็นมีอะไรเกี่ยวกับการทำงาน เพราะบทความนั้นอยากให้เน้นไปทางคำสั้งที่ส่วนมากที่ใช้งานมากกว่า เดียวเราไปเข้าเรื่องกันเลย เหมือนจะพูดวนไปวนมา 😁😁😁
Git Branch
ที่จริงความหมายก็จะแปลตรงตัวเลย นะ เพราะคำว่า Branch ก็แปลว่า สาขา นั้นก็หมายความว่า git branch ก็คือการทำงานแบ่งย่อยเป็นสาขานั้นแหละ ตัวอย่างเช่น
เมื่อเรามี Project อยู่หนึ่งตัวแล้วมีคนทำสองคน เดียวจะจำลองเป็นนาย ก. กับ นาย ข. ละกัน ก่อนอื่นเราจะยังไม่ได้พูดถึง git ก่อนนะ
ทำงานรวมกันแบบไม่มี git ( version มะโนเอง )
เมื่อนาย ก. และ นาย ข. เอาโปรเจคไปทำนั้นเมื่อทำโปรเจคเสร็จแล้วจะต้องมารวมโปรเจคกันด้วยการใช้ flash drive
ซึ่งสิ่งที่เป็นปัญหาก็คือเมื่อ 2 เครื่องนี้ทำงานเสร็จเรียบร้อยก็ต้องหา คอมมาหนึ่งเครื่องเพื่อที่จะใช้รวม Project ปัญหามันยังไม่หมดแค่นี้สิ มันก็ต้องมีการมารวมหัวกันเพื่อที่จะมาบอกว่าใครแก้ไขอะไรไป ตอน project ยังไม่ใหญ่คงไม่มีใครเห็นปัญหาพอเราแก้ไขไปเยอะ ละ เริ่มจะมีความซับซ้อนเครื่องคอมตัวกลางเกิดพังขึ้นมาละ เศร้ากันเลยงานนี้
เริ่มใช้งาน git กับ Project
เมื่อเริ่มใช้ git เหมือนพระเจ้าทรงโปรด เพราะ git มาช้วยให้เวลาเราเอางานส่งหากันง่ายขึ้น โดยเราก็ไม่ต้องซื้อคอมมาเพิ่มเพื่อเก็บ file project เพียงแค่เอาขึ้นไปเก็บไว้บน git host เช่น github ก็สบายขึ้นมาก แต่มันก็ยังมีปัญหาเวลาเราใช้ git ตอนแรกๆ มันจะสร้าง branch ให้เรา ชื่อ master อยู่แล้วใช้ไหม
ผมสมมุติเวลาเราทำงาน ใน branch เดียวกัน ตัวอย่างแรกเลย เมื่อนาย ก. push
code ส่วน feature 2 ขึ้นไป แล้ว นาย ข. จะpush
code ส่วน feature 3 ขึ้นไป ปัญหาคือเมื่อนาย ก. push
นาย ข. ต้อง pull มาก่อน ถึงจะ push
ไปได้ ทำให้เสียเวลา ปัญหานี้อาจไม่ยิ่งใหญ่เท่าปัญหาถัดไป
Conflict
ตัวนี้ถ้าใครใช้ git ไม่เคยเจอถือว่าใช้ไม่คุ้ม แต่คนที่เจอแล้วก็ไม่อยากจะให้เจอมันอีกเลยขี้เกียจมานั้งแก้ ซึ่ง Conflict
มันจะเกิดขึ้นก็ต่อเมื่อ เรากับเพื่อนเราเขียนแก้ไขข้อมูล ไฟร์เดียวกัน ณ ตำแหน่งเดียวกัน จากนั้น ใคร push
ก่อนได้เปลียบละ นะวินาทีนั้น เราก็ต้องกลับมาใช้ soft skill เหมือนเดิมคือการมานั้งคุยกัน แต่มันดีกว่าวิธีแรกมาก เพราะมันจะเอา code ของทั้ง สอง คนมาเลือกกันไปเลยว่าจะใช้วิธีไหน
ส่วน A
ส่วน code ที่เพื่อนเรา push
มาแล้ว แล้วเรา pull
มาเจอะ Conflict
ส่วน B
จะเป็นส่วนขั้นว่า code ของเพื่อนเราที่ push
มาก่อนหน้านั้นถึงแค่นี้นะ
ส่วน C
ก็คือนับตั้งแต่เส้น B
มาจนถึง C
นี้แหละคือ code ของเราที่ไปเขียนทับกัน
ก็มานั้งคุยกันเมื่อตกลงกันได้จะใช้ของใคร สมมุติว่าใช้ของเราใช้ไหม เราก็ลบของเพื่อเราออก ต้ังแต่ A
ไปยัง B
แล้วอย่างลืมลบ บรรทัด C
ด้วยถ้าไม่ลบนี้ได้เจอ error แน่นอน
แตกสาขาแยกงานกันทำ ด้วย git branch
เรามา อัพ level กันอีกหน่อยเพื่อที่จะให้การทำงานเป็น team เป็นไปอย่างง่ายมากขึ้น
เมื่อเราแยก branch ข้อดีคือ ลบปัญหาต้องมารอpull
code ของแต่ละคนแล้วถึงจะเพิ่ม code ไปได้ เพราะเราแยกทำงานอยู่คนละ branch กันแล้ว น่าตาของ tree ที่เราจะเห็น จะประมาณนี้
แต่ถ้าเราสังเกตุดู งานนาย ก. และ งานนาย ข. นั้น ยังมี feature ที่เหมือนกันอยู่เวลาเรารวม code กัน ทำให้เจอปัญหาเดิม คือ เจ้าConflict
( คุณมุงยังอยู่อีกหรอแวะ ) แต่เมื่อเราแยก branch แล้วเราก็แก้ไข ได้ง่ายๆ โดยการ แยก branch ออกเป็นงาน ไป แค่นี้ก็ปิดปัญหาการเกิด Conflict
เรียบร้อย
แต่เมื่อเรากำจัดเจ้าConflict
ไปแล้วเราก็กลับมาทำ Project ของเราชิวๆ ได้เลย เปิดแอร์ จิบกาแฟ ไปชิวๆ จน Project เริ่มโต จะอุทาน เหี้ยแล้ว ( เหี้ย เป็นสัตว์เลื้อยคลานในเอเชียใต้และเอเชียตะวันออกเฉียงใต้ ) ชื่อ branch มั่วไปหมด ไม่รู้ว่า branch ไหน เป็น branch ไหน ผมก็เคยอยู่วังวนนี้เหมือนกัน ถึงตอนนี้ยังหนีมันไปยังไม่ค่อยจะพ้นเลย จนมาเจอกับ ….
Git Flow
git flow
เจ้านี้จะมาดึงความสามารถของ การใช้ Branch ได้อย่างมีประสิทธิภาพมากขึ้น โดยผมจะแยก Branch ออกเป็น 5 Branch
- master ← เป็น branch ที่มีอยู่ก่อนหน้านี้อยู่แล้ว- develop- feature- release- hotfix
Branch Master
อันที่จริง branch นี้ จะเป็น branch ที่ถูกสร้างขึ้นมาเริ่มต้นอยู่แล้ว ซึ่งเราไม่ต้องสร้างมันขึ้นมาโดย branch master นี้เราจะให้เป็น branch ที่ใช้สำหรับเก็บ project ตอนเป็น product ซึ่งก็คือเวลาเราทำ project ใช้ไหม เราก็ setting ทุกอย่างให้พร้อมก่อนที่จะเอาเข้ามาใน branch นี้ เพราะ branch นี้เราจะใช้สำหรับ deploy ขึ้น server ไปเลย
Branch Develop
ส่วนของ branch develop นั้น เราจะทำการแตกออกจาก branch master อีกที โดยเราจะให้ branch นี้ไว้สำหรับ นักพัฒนา program ของเรา พัฒนา เอา code เมื่อเสร็จแล้วมาเก็บใน ที่นี้เพื่อลอง test ยำๆ ซ้ำๆ กันก่อนว่ามี error หรือ bug ไหมถ้ามีเราก็แก้ไขในส่วนนี้ก่อนเลย โดยเวลาเราจะสร้างจาก branch master
# ถ้าตอนนี้เราอยู่ใน branch master เราจะทำการสร้าง branch develop ขึ้นมาโดยใช้
$ git branch develop# จากนั้นเราจะทำการเข้าไปใช้ branch develop นั้น
$ git checkout develop$ git branch # ตรวจสอบ branch ของเรา
$ git branch --all # ตรวจสอบ branch ของเราทั้งหมด$ git branch --delete develop # ลบ branch ชื่อ develop
Branch Feature
ส่วน branch นี้เราจะต้องแตกมาจาก branch develop เท่านั้น [ย้ำตัวหนาๆ เลย]
เพราะใน branch นี้เราจะเอาไว้ให้ นักพัฒนาของเราพัฒนา feature แต่ละส่วน โดยเราจะแบ่งงานอย่างชัดเจน เช่น อย่างเราจะทำ ระบบสมาชิก เราก็จะแบ่งออกเป็นงานเลย ก็จะมี สมัครสมาชิก , เข้าสู่ระบบ , ระบบ Profile และ อื่นๆ ซึ่งเวลาเราแยก branch ออกเราก็แยกเป็น feature ไปเลย เช่น สมัครสมาชิก => feature/register
อย่างงี้เป็นต้น เราจะไม่เอา งานที่เราทำเข้าสู่ระบบสมาชิก เด็ดขาดไม่งันเราก็ต้องกลับไปเจอปัญหาเดิมที่เคยกล่าว Conflict
ถ้าเราทำเสร็จก็ทำการ ลบ branch ทิ้งไป หรือใครอยากเก็บไว้ก็แล้วแต่ แต่มันจะเยอะมาก เพราะ 1 project ของเราคงไม่มีแค่งานเดียวหรอกใช้ไหม
# เราต้อง checkout ไปที่ branch develop ก่อน
$ git checkout develop# ทำการ สร้าง feature ชื่อว่า profile_management
$ git branch feature/profile_management# จากนั้นทำการ checkout branch feature/profile_management เพื่อใช้งาน
$ git checkout feature/profile_management
เมื่อเราทำงานส่วนของ feature แต่ละตัวเรียบร้อยแล้วถึงขั้นตอน merge code ขั้นตอนนนี้ก็ไม่ยาก ก่อนอื่นอย่าลืม git commit , git push ให้เรียบร้อยก่อนนะ
# จากนั้นเราจะทำการกลับไปที่ branch develop
$ git checkout develop# แล้วทำการ merge code เข้ามาใน develop
$ git merge feature/profile_management# ทำการลบ branch feature/profile_management
$ git branch --delete feature/profile_management
ก็เป็นการเรียบร้อย
แต่ แต่ แต่ …..
มีใครเอะใจไหม ว่าเห้ยจริงหรอที่ใครก็ได้จะทำการ merge เข้า develop ได้ ผมลองยกตัวอย่าง เมื่อเราทำระบบ profile เสร็จแล้วใช้ไหม เราก็ไปทำงานอื่นต่อเพราะเรา test ในเครื่องเราทำงานได้ ปกติ ….. พอตก 1 เดือนผ่านไป วันที่เราเอา code มารวมกับเพื่อนใน branch develop เพื่อที่จะ test ดันมาเกิดปัญหาใน ส่วน profile ที่เราทำสะได้ งานงอกละทีนี้ตรูเขียนอะไรไปแวะเนีย ลืมไปหมดแล้ว แทนที่เราจะได้ทำ งานที่วาง timeline ในวันนี้ก็กลายเป็นแก้ไขงานเดิมไป หนึ่งวัน
แต่ที่จริงวิธีนี้ก็มีทางแก้ไข ( เพราะทุกปัญหามีทางออก ) เราก็มาใช้ review code สิ จบเรื่อง แต่ review code มันใช้ไงพี่ เดียวแปะ บทความนี้ลองอ่านกันดูน่าจะพอเห็นภาพมันมากขึ้น
Branch Release
Release ก็เหมือนเดิม branch develop เท่านั้น [ย้ำตัวหนาๆ เลย]
แต่หน้าที่ของตัวนี้จะแตกต่างจาก branch feature ที่เราเคยกล่าวกันไปก่อนหน้า เพราะ อันที่จริงเราก็แปลตามชื่อไปเลย release => ปล่อย
พิมพ์แบบนี้น่าจะ งง อันที่จริง branch release นั้นเราจะใช้สำหรับส่งให้ tester ไป check อีกครั้งหลังจาก นักพัฒนาได้ ตรวจสอบจาก branch develop ไปแล้ว ก็ให้ tester ตรวจแบบละเอียดอีกทีก่อนที่จะ launch ออกเป็น product ซึ่งการสร้าง branch release ก็แล้วแต่ เทคนิคแต่ละคน บ่างคน อาจจะ สร้างเป็น branch release/0.0.1
หรือ บ่างคนอาจจะใช้เป็น tag (ซึ่งเดียวจะไปพูดกันอีกที) ก็ได้ ซึ่งกรณีนี้ผมยกตัวอย่างเป็น release/0.0.1
ก่อนเพื่อเข้าใจง่าย
# จากนั้นเราจะทำการกลับไปที่ branch develop
$ git checkout develop# สร้าง branch release/0.0.1 สำหรับให้ tester check ก่อน launch program
$ git branch release/0.0.1# ทำการ checkout ไปที่ branch release/0.0.1 เพื่อ test program สำหรับ tester
$ git checkout release/0.0.1
เมื่อ tester ตรวจสอบเสร็จสิ้น ไม่มีปัญหาอะไรเกิดขึ้นเราก็จะทำการ merge branch release ที่เราได้ทำการเตรียมปล่อยให้เป็น product นั้นไปเข้ากับ branch master , develop
ทำไมเราถึงต้อง merge เข้า 2 branch ละ ??
master
เพราะ เมื่อเราตรวจสอบเสร็จแล้วเราก็ต้อง อัพข้อมูลให้เป็นงานที่เสร็จแล้วสำหรับส่งให้ลูกค้า
develop
เพราะ เมื่อส่งงานให้ลูกค้าแล้วอาจมีงานที่เราจะได้ พัฒนาต่อไปก็ทำการเตรียมไว้ใน branch develop ให้เป็น version ล่าสุดก่อนเลย
# ทำการ checkout ที่ branch release/0.0.1
$ git checkout release/0.0.1# เมื่อตรวจเสร็จ ทำการ merge เข้า master , develop
$ git merge master
$ git merge develop
Branch Hotfix
เราจะทำการแตกจาก branch ที่เป็น product หรือ branch master เพื่อที่จะทำการแก้ไขbranch masterเท่านั้น [ย้ำตัวหนาๆ เลย]
โดย branch นี้หน้าที่หลักๆ เราจะเอาไว้แก้ไข แบบกระทันหัน เช่น เมื่อลูกค้าต้องการให้แก้ไขบ่างส่วนแบบด่วน เราก็เอามาแก้ไขใน branch นี้นั้นเอง อันนี้จะเป็นตัวอย่างที่ผมเริ่มทำ project เพียงไม่กี่คน นะ
# ทำการสร้าง branch สำหรับ แก้ไขแบบด่วน
$ git branch hotfix/loginError# เมื่อทำการแก้ไข เสร็จก็ทำการ merge เข้า branch master , develop
$ git merge master
$ git merge develop
Git Tag
git tag
จะเป็นการวางตำแหน่ง mark ไว้ว่าโปรแกรมที่เราพัฒนาอยู่ ใน commit นี้เป็น version อะไรแล้ว โดยส่วนมากจะ mark ไว้ที่ trunk (เส้นหลัก ใช้กับ master หรือ release ก็ได้) ว่า version ที่เราได้ปล่อยไปนี้เราพัฒนาอยู่ version อะไรแล้ว
# สร้าง tag ขึ้นมา
$ git tag <tagname>
$ git tag my_tag# สร้าง tag ขึ้นมาแบบระบุข้อความ
$ git tag -a <tagname> -m "message"
$ git tag -a my_tag -m "crate tag v0.0.1"# แสดง tag ทั้งหมด
$ git tag
$ git tag -l
$ git tag -list#ลบแท็กชื่อ my_tag
$git tag --delete my_tag#ส่งแท็กขึ้นไปที่ Remote Repository
$git push origin <tag name> #ส่งแท็กทั้งหมดขึ้นไปที่ Remote Repository
$git push origin --tags#ลบแท็กที่ Remote Repository
$git push --delete origin <tag name>
ลองอ่านต่อได้ที่
Git Merge
git merge
เป็นคำสั่งที่ใช้สำหรับ รวม code จาก branch นึงมาอีก branch นึงโดย ถ้าเราเอาใช้งานจริงเช่น ถ้าเราแยกงาน กับเพื่อนจาก master แยกออกมาเป็น branch A
และ branch B
อันนี้สาธิต ให้ดูว่า ถ้า branch A และ branch B ทำการแก้ไข เสร็จแล้วนะ
# ทำการ checkout ไป branch master ก่อน
$ git checkout master# ทำการ merge branch A เข้าไป branch master
$ git merge A# ทำการ merge branch B เข้าไป branch master
$ git merge B# รวม branch master กับ branch feature แบบ no fast forward
$ git merge --no-ff < branch ># รวม branch master กับ branch feature แบบ fast forward
$ git merge < branch >
Git Checkout
git checkout
เป็นคำสั่งที่ใช้สำหรับสลับ ไปยัง branch หรือ Commit ที่เราเคยสร้างไว้
# ย้ายการทำงานไปที่ Branch หรือ commit_id ที่ระบุ $ git checkout <branch name || commit id># สร้าง branch ชื่อ test และทำการสลับการทำงานมาที่ Branch นี้
$ git checkout -b test# ยกเลิกการเปลี่ยนแปลงของไฟล์ใน Working Directory
$ git checkout -- <file name># เลือกแค่บางไฟล์จาก Branch อื่น เข้ามา Merge กับ Working Directory ที่กำลังทำงาน
$ git checkout <branch name> <file name># คำสั่งนี้จะเหมือนคำสั่งด้านบนแต่จะมีโหมดตอบโต้กับผู้ใช้ในการเลือกสถานะของไฟล์ที่ระบุ
$ git checkout --patch <branch name> <file name>
เข้าใจ Fork และ Pull Request
อันนี้อาจจะไม่ได้อธิบายถึง การใช้สักเท่าไหร่ เพราะผมก็ยังไม่ได้ โหดขนาดที่จะได้ใช้พวกนี้มา เหมือน กัน แต่นี้เราเอาที่เราได้อ่านจากหลากหลาย blog มาแล้วพอเข้าใจกะเลยอยาก share
Fork
Fork
คือการที่เรา เอา Repository ของคนอื่นนั้นมาเก็บไว้ใน Repository ของราเพื่อทำการแก้ไข เพราะเวลาเราเอา Project ที่อยู่ใน github ของคนอื่นมานั้น แม้ว่าจะเป็น Public Repository ก็ตาม
สมมุติว่า เราใช้ Library คนอื่นมาใช้ แล้วเกิดมี bug ถ้าเราอยากแก้ไข ใน Repository ของเขามันไม่สามารถแก้ไขได้ใช้ไหม เราก็ตอง Fork Project ของเขามาก่อนเพื่อที่จะทำการแก้ไข แล้วนำ Library นั้นมาใช้งานได้
Pull Request
Pull Request
นั้นก็ต่อมาจากตัว Fork เลย แต่หน้าที่ไม่ได้เหมือนกัน เพราะ Pull Request นั้นจะทำก็ต่อเมื่อเราทำการแก้ไข File ของเราแล้วเราต้องการ merge งานของเราเข้าไปกับคนอื่น ก็ทำการ Pull Request เข้าไปเพื่อขออนุญาติ merge File เข้ากับงานของเขา
สมมุติว่า ผม Fork งานคนอื่นมาใช้ไหมแล้วก็ทำการแก้ไขงานที่ bug ไปแล้ว แล้วต้องการช้วยคนอื่นว่าส่วนนี้ bug นะ แล้วก็ ทำการ Pull Request ไปให้คนอื่น เพื่อที่จะเอา code ที่เราได้แก้ไข Library ที่มันเป็น Bug นั้นส่งให้เจ้าของ Library ซึ่งการ Pull Request นั้นเจ้าของ Library สามารถเลือกที่จะเอา code เราหรือไม่ก็ได้
ทำให้เกิด Open Source ขึ้นมานั้นเอง
จะไปดูการที่เขาอธิบายการ ทำ Fork และ Pull Request แบบละเอียดได้ที่นี้เลย
ทั้งนี้ทั้งนั้นก็ยังยืนยันว่า ใช้ git แล้วชีวิตการทำงานเป็นทีมจะสดใสมากขึ้น
Blog นี้ไม่ค่อยฟิตเลยเขียน โคตรนาน 😁😁😁😁😁😁😁😁😁😁