บทที่ 3 ทำงานเป็นทีมบน GitHub: GitHub flow, pull request และ code review
แผนบริหารการสอนประจำบทที่ 3
หัวข้อเนื้อหา
- 3.1 remote repository: clone, push, fetch และ pull
- 3.2 GitHub flow และ pull request
- 3.3 protected branch: การป้องกัน branch หลัก
- 3.4 GitFlow, GitHub flow และ Trunk-Based Development
- 3.5 code review ที่มีคุณภาพ
- 3.6 กรณีศึกษา: การเลือก Git workflow ให้เหมาะกับทีม
- 3.7 เส้นทางของการเปลี่ยนแปลงจากเครื่องหนึ่งสู่ทีม
- 3.8 pull request เป็นข้อเสนอที่มีหลักฐาน
- 3.9 การให้ความเห็นที่นำไปปรับงานได้
- 3.10 กติกาที่ป้องกันความผิดพลาดและข้อจำกัดของกติกา
- ปฏิบัติการที่ 3 การทำงานเป็นทีมบน GitHub (Lab A–D)
วัตถุประสงค์เชิงพฤติกรรม
เมื่อศึกษาบทนี้และทำปฏิบัติการครบถ้วนแล้ว ผู้เรียนสามารถปฏิบัติได้ตามผลลัพธ์การเรียนรู้ต่อไปนี้ โดยแต่ละข้อมีงานที่ใช้วัดผลกำกับไว้
| รหัส | ผลลัพธ์การเรียนรู้ | วัดจาก | CLO ของรายวิชา |
|---|---|---|---|
| 3.1 | ตั้ง branch protection และทำงานตาม GitHub flow ครบ 6 ขั้นใน repository ของทีม | งานข้อ 1 | CLO2 |
| 3.2 | อธิบายเหตุผลในการเลือก GitHub flow หรือ GitFlow สำหรับโจทย์ทีมที่กำหนด 2 สถานการณ์ | งานข้อ 3 | CLO1 |
| 3.3 | ให้ความเห็นด้านคุณภาพใน pull request ของสมาชิกทีมอย่างน้อย 1 ข้อพร้อมเหตุผล | งานข้อ 2 | CLO4 |
| เตรียมพื้น | ส่ง repository เดี่ยว devops-lab01 จากบทที่ 2 ขึ้น GitHub พร้อม tag v0.1.0 | งานข้อ 4 | ยังไม่นับ CLO |
CLO ที่เกี่ยวข้อง (ข้อความจากหลักสูตร):
- CLO1 สามารถนำความต้องการและสถาปัตยกรรมการส่งมอบซอฟต์แวร์ที่กำหนดมาใช้ โดยอธิบาย Git workflow, CI/CD pipeline flow และการใช้ Containerization ได้อย่างเหมาะสมกับบริบทของงาน
- CLO2 สามารถกำหนดค่าและใช้งาน DevOps workflow ที่กำหนดมา เพื่อให้กระบวนการพัฒนา–ทดสอบ–ส่งมอบซอฟต์แวร์เป็นไปอย่างถูกต้องและมีประสิทธิภาพ
- CLO4 ผู้เรียนแสดงออกถึงความรับผิดชอบและความใฝ่รู้ในการเรียนรู้เทคโนโลยีและเครื่องมือใหม่ที่เกี่ยวข้องกับ DevOps โดยศึกษาค้นคว้าด้วยตนเองจากแหล่งข้อมูลที่เชื่อถือได้ และปฏิบัติตามแนวปฏิบัติด้านความปลอดภัยและคุณภาพของระบบ
บทนี้เป็นบทแรกที่ทำงานเป็นทีม (ทีมละ 3 คน) และใช้ repository ทีมเดียวต่อเนื่องจนจบภาคการศึกษา หลักฐานทุกข้อยังเก็บเป็นรายบุคคล ได้แก่ pull request ของแต่ละคน ความเห็นใน review ของแต่ละคน และใบงานกรณีศึกษาที่เขียนเดี่ยว
วิธีสอนและกิจกรรมการเรียนการสอน
- บรรยายแนวคิดตามหัวข้อ 3.1–3.5 ประกอบตัวอย่างที่ซับซ้อนขึ้นตามลำดับ และใช้คำถามตรวจความเข้าใจท้ายหัวข้อเป็นกิจกรรมอภิปรายเป็นคู่
- สาธิตการเปิด pull request การ review และการ merge บน repository ตัวอย่างของผู้สอน
- อภิปรายกรณีศึกษาในหัวข้อ 3.6 เป็นกลุ่ม แล้วให้ผู้เรียนเขียนคำอธิบายรายบุคคล
- ปฏิบัติการ Lab A–D บน repository ทีม แต่ละ Lab ประกอบด้วยส่วนฝึกตามตัวอย่างและส่วนที่ผู้เรียนต้องตัดสินใจเอง
- มอบหมายแบบฝึกหัดท้ายบท งานที่ต้องส่ง Learning Log ครั้งที่ 3 และการศึกษาค้นคว้าเพิ่มเติม
สื่อการเรียนการสอน
- เอกสารประกอบการสอนบทที่ 3 (บทความนี้) และหน้ารวมรายวิชา 10306343
- เครื่อง Ubuntu 24.04 ที่ติดตั้ง Git แล้ว และโฟลเดอร์
~/devops-lab01จากบทที่ 2 - บัญชี GitHub ของผู้เรียนทุกคน
- ไฟล์แอปตั้งต้น
devops-appที่ผู้สอนแจก (Node.js และ Express พร้อม endpoint/healthและ unit test) - เอกสารทางการ GitHub Docs หัวข้อ GitHub flow, About pull requests และ About protected branches
การวัดผลและการประเมินผล
กำหนดส่ง: ก่อนเริ่มเรียนบทที่ 5 เพื่อเว้นระยะหนึ่งบท
| ข้อ | งาน | หลักฐาน | ผลลัพธ์ | CLO |
|---|---|---|---|---|
| 1 | M2 pull request ของตนเอง | ลิงก์ pull request ของตนที่ merge แล้วผ่าน review อย่างน้อย 1 ครั้ง ซึ่งคำอธิบายกรอกตาม template ของทีม ภาพหน้าตั้งค่า branch protection ของ main และไฟล์ .github/pull_request_template.md ใน repository ทีม | 3.1 | CLO2 |
| 2 | ความเห็นใน code review | ลิงก์ความเห็นของตนใน pull request ของสมาชิกทีม ที่ระบุตำแหน่งและเหตุผลด้านคุณภาพ | 3.3 | CLO4 |
| 3 | ใบงานกรณีศึกษา (CLO1 ชิ้นที่ 1) | คำอธิบายรายบุคคลไม่เกิน 1 หน้า ตอบกรณีศึกษาทั้ง 2 สถานการณ์ในหัวข้อ 3.6 | 3.2 | CLO1 |
| 4 | repository เดี่ยวบน GitHub | ลิงก์ repository devops-lab01 ที่มีประวัติจากบทที่ 2 และ tag v0.1.0 | เตรียมพื้น | ยังไม่นับ CLO |
| 5 | Learning Log ครั้งที่ 3 | ตอบ 4 หัวข้อ: สิ่งที่เรียนในบทนี้ · ขั้นตอนใดของ GitHub flow ที่ยังไม่มั่นใจ · แหล่งที่ใช้ค้นหาคำตอบ (ระบุลิงก์เอกสารทางการอย่างน้อย 1 แหล่ง) · ความเห็น review ที่ได้รับแล้วนำไปปรับงานอย่างไร | — | บันทึกสะท้อนการเรียนรู้ ไม่มีหมวดคะแนน portfolio แยก |
เกณฑ์ให้คะแนน
| ข้อ | ผ่าน | ยังไม่ผ่าน |
|---|---|---|
| 1 | pull request ของตนผ่าน review อย่างน้อย 1 ครั้ง merge เข้า main ผ่าน pull request เท่านั้น คำอธิบายกรอกครบตามหัวข้อของ template และ branch protection บังคับ approval อย่างน้อย 1 ครั้ง | merge โดยไม่มี review, push ตรงเข้า main หรือไม่มี template |
| 2 | ความเห็นระบุจุดที่เกี่ยวข้อง (ไฟล์หรือบรรทัด) และให้เหตุผลด้านคุณภาพ | ความเห็นทั่วไป เช่น "ดีแล้ว" หรือไม่มีเหตุผล |
| 4 | repository มีประวัติ commit จากบทที่ 2 และมี tag v0.1.0 | ไม่มีประวัติเดิม หรือไม่มี tag |
| 5 | ตอบครบ 4 หัวข้อ และมีลิงก์เอกสารทางการ | ขาดหัวข้อ หรือไม่มีแหล่งอ้างอิง |
ข้อ 3 ใช้ rubric CLO1 3 ระดับ
| ระดับ | ลักษณะของคำตอบ |
|---|---|
| 3 ดี | เลือก workflow ให้แต่ละสถานการณ์พร้อมเหตุผลที่โยงกับบริบท และเทียบทางเลือกอย่างน้อย 2 ทางพร้อมข้อแลกเปลี่ยน |
| 2 ผ่าน | เลือก workflow ถูกต้องกับบริบทของทั้งสองสถานการณ์ และอธิบายลำดับการทำงานและเหตุผลได้ |
| 1 ยังไม่ผ่าน | ท่องนิยามของ workflow โดยไม่โยงกับสถานการณ์ หรือเลือกโดยไม่มีเหตุผล |
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
การคิดคะแนนฉบับปัจจุบัน
มติผู้สอน 28 ต.ค. 2569: เข้าเรียน 10% · ใบงานบทที่ 1–13 รวม 40% · FP 20% · FW 20% · โครงงาน 10% ส่วนบทที่ 14–15 ฝึกเพื่อรับข้อเสนอแนะ ไม่นับคะแนน
ใบงาน C03-WS01 มีคะแนนดิบเต็ม 30 คะแนน แยกตามผลลัพธ์ด้านล่าง ระบบนำไปรวมในหมวดใบงาน 40% โดยไม่เพิ่มคะแนน milestone, portfolio หรือจุดตรวจเป็นหมวดแยก
| ผลลัพธ์ | หลักฐานตามงานส่ง | คะแนนดิบเต็ม |
|---|---|---|
| LLO3.1 | งานข้อ 1 | 10 |
| LLO3.2 | งานข้อ 3 | 10 |
| LLO3.3 | งานข้อ 2 | 10 |
ประเมินงานแต่ละข้อจากหลักฐานของข้อนั้นโดยตรง ไม่ตัดสิทธิ์รับคะแนนของอีกข้อเพราะ milestone หรือจุดตรวจอื่นยังไม่ผ่าน งานที่ยังทำไม่ได้ให้บันทึกปัญหาและหลักฐานที่มีตามจริง
ใช้เกณฑ์ความถูกต้อง เหตุผล และหลักฐานที่ระบุในงานแต่ละข้อประกอบการประเมินราย LLO งานเตรียมพื้นและ Learning Log ที่ไม่มีรหัส LLO ใช้ให้ข้อเสนอแนะ ไม่เพิ่มคะแนนดิบให้ใบงาน
บทนำ
บทนี้ขยายการใช้ Git จาก repository บนเครื่องเดียวในบทที่ 2 ไปสู่การทำงานร่วมกันเป็นทีมผ่าน GitHub ซึ่งเป็นบริการเก็บ repository บนเครือข่าย (remote repository) และเป็นจุดรวมงานของสมาชิกทุกคน เนื้อหาเริ่มจากกลไกการส่งและรับงานระหว่าง repository ในเครื่องกับ remote จากนั้นอธิบาย GitHub flow ซึ่งเป็น workflow หลักของรายวิชา pull request ซึ่งเป็นช่องทางเสนอการเปลี่ยนแปลงและตรวจทานงาน protected branch ซึ่งบังคับให้ทุกการเปลี่ยนแปลงผ่านการตรวจทาน และการเปรียบเทียบกับ GitFlow และ Trunk-Based Development เพื่อให้เลือก workflow ได้เหมาะกับบริบทของงาน
ความสำคัญ: repository ของทีมที่สร้างในบทนี้คือแหล่งความจริงเดียว (Single Source of Truth) ตามที่กล่าวไว้ในบทที่ 2 ทุกบทหลังจากนี้ทำงานผ่าน pull request บน repository นี้ บทที่ 5 ให้ระบบ CI ตรวจ pull request ทุกรายการก่อน merge และบทที่ 8 deploy แอปทุกครั้งที่ main เปลี่ยน การป้องกัน main ให้รับเฉพาะงานที่ผ่านการตรวจทานจึงเป็นเงื่อนไขของความน่าเชื่อถือของทั้งระบบ
ความเชื่อมโยงกับบทอื่น: บทนี้ใช้คำสั่ง commit, branch, merge และการแก้ merge conflict จากบทที่ 2 และกติกา Branch-First ที่กำหนดให้งานทุกชิ้นเริ่มบน branch ใหม่ ผลผลิตของบทนี้ถูกใช้ต่อตามตารางต่อไปนี้
| สิ่งที่ได้จากบทนี้ | ใช้ต่อในบท |
|---|---|
repository ทีม devops-app บน GitHub | 4 ถึง 13 (ทุกบท) |
branch protection ของ main | 5 (เพิ่ม required status check ของ CI) |
| การทำงานผ่าน pull request และ code review | ทุกบท ใช้เก็บหลักฐานรายบุคคลของงานทีม |
repository เดี่ยว devops-lab01 บน GitHub | หลักฐาน M1 ของบทที่ 2 |
ความรู้พื้นฐาน เครื่องมือ และรุ่นซอฟต์แวร์
ความรู้พื้นฐาน: คำสั่ง Git จากบทที่ 2 ได้แก่ commit, branch, switch, merge และการแก้ merge conflict รวมถึงการอ่านกราฟจาก git log --oneline --graph
เครื่องมือ: เครื่อง Ubuntu ที่ติดตั้ง Git แล้วและโฟลเดอร์ ~/devops-lab01 จากบทที่ 2 บัญชี GitHub ของผู้เรียนทุกคน และไฟล์แอปตั้งต้น devops-app ที่ผู้สอนแจกให้หัวหน้าทีม
รุ่นซอฟต์แวร์ที่ใช้ทดสอบ:
| ซอฟต์แวร์ | รุ่นที่ทดสอบ |
|---|---|
| Git | 2.43.0 บน Ubuntu 24.04.5 (ทดสอบเมื่อ 18 ต.ค. 2569 โดยใช้ bare repository ในเครื่องแทน GitHub) |
| GitHub (เว็บ) | ยังไม่ได้ทดสอบขั้นตอนบนหน้าเว็บในรอบนี้ ขั้นตอนอ้างอิงจาก GitHub Docs |
คำสั่ง Git ฝั่งเครื่องผู้เรียนทั้งหมดทดสอบแล้วกับ remote ที่จำลองด้วย bare repository ผลลัพธ์เมื่อเชื่อมต่อ GitHub จริงจะมีบรรทัดเพิ่ม เช่น ความคืบหน้าของการส่งข้อมูล (Enumerating objects, Writing objects) และข้อความที่ขึ้นต้นด้วย remote: ซึ่ง GitHub ส่งกลับมา ชื่อเมนูบนหน้าเว็บ GitHub อาจเปลี่ยนตามรุ่นของบริการ
ค่าใช้จ่ายและข้อมูลลับ: บัญชี GitHub แบบไม่มีค่าใช้จ่าย (GitHub Free) เพียงพอสำหรับบทนี้ ประเด็นที่ต้องระวังมีสามประการ ประการแรก GitHub ไม่รับรหัสผ่านของบัญชีสำหรับคำสั่ง Git ผ่าน HTTPS การ push ต้องใช้ personal access token หรือ SSH key ซึ่งถือเป็นข้อมูลลับ ห้ามบันทึกลงในไฟล์ใดของ repository และควรกำหนดวันหมดอายุของ token ประการที่สอง ชื่อและอีเมลใน user.name และ user.email จะปรากฏในประวัติ commit ที่เปิดเผยต่อสาธารณะ ประการที่สาม branch protection ของ repository แบบ private อาจต้องใช้แผนบริการแบบมีค่าใช้จ่าย รายวิชาจึงกำหนดให้ repository ทีมเป็นแบบ public ซึ่งปลอดภัยเพราะไฟล์ลับถูกกันด้วย .gitignore ตั้งแต่บทที่ 2 และจะย้ายความลับไป GitHub Secrets ในบทที่ 10
3.1 remote repository: clone, push, fetch และ pull
remote repository คือ repository อีกชุดหนึ่งที่อยู่บนเครื่องอื่นหรือบนบริการเครือข่าย เช่น GitHub Git เป็นระบบควบคุมเวอร์ชันแบบกระจาย repository ในเครื่องของสมาชิกแต่ละคนจึงมีประวัติครบทั้งชุด การทำงานเป็นทีมอาศัยการส่งและรับ commit ระหว่าง repository ในเครื่องกับ remote ที่ทีมตกลงให้เป็นแหล่งความจริงเดียว โดย remote ที่ใช้บ่อยที่สุดมีชื่อเรียกตามธรรมเนียมว่า origin
| คำสั่ง | ทิศทาง | หน้าที่ |
|---|---|---|
git clone URL | remote → เครื่อง | คัดลอก repository ทั้งชุดมาเป็น repository ใหม่ในเครื่อง และตั้ง origin ให้อัตโนมัติ |
git remote add origin URL | — | ผูก repository ในเครื่องที่มีอยู่แล้วเข้ากับ remote ใหม่ |
git push | เครื่อง → remote | ส่ง commit ของ branch ในเครื่องขึ้น remote |
git fetch | remote → เครื่อง | ดึงข้อมูล commit ใหม่จาก remote มาเก็บในตัวชี้ชื่อ origin/ชื่อbranch โดยไม่แก้ไขงานในเครื่อง |
git pull | remote → เครื่อง | git fetch แล้วรวม (merge) commit ที่ได้เข้ากับ branch ปัจจุบัน |
ระดับที่ 1 การ push ครั้งแรก: คำสั่ง git push -u origin main ส่ง branch main ขึ้น remote และตัวเลือก -u บันทึกความสัมพันธ์ (upstream) ระหว่าง main ในเครื่องกับ origin/main หลังจากนั้นสั่ง git push หรือ git pull เปล่า ๆ ได้ tag ไม่ถูกส่งไปพร้อม branch ต้องส่งแยกด้วย git push origin --tags
ระดับที่ 2 ความต่างระหว่าง fetch กับ pull: ข้อความ Your branch is up to date with 'origin/main' ในผลของ git status เทียบกับข้อมูล origin/main ที่ดึงมาครั้งล่าสุดเท่านั้น หากสมาชิกคนอื่น push งานใหม่หลังจากนั้น ข้อความนี้ยังคงแสดงจนกว่าจะสั่ง git fetch หรือ git pull อีกครั้ง
ระดับที่ 3 การ pull เมื่อสองฝั่งมี commit ใหม่: หาก branch ในเครื่องและ remote ต่างมี commit ใหม่ของตนเอง (divergent branches) Git รุ่นปัจจุบันจะหยุดและขอให้เลือกวิธีรวมงานก่อน รายวิชานี้รวมงานด้วย merge เช่นเดียวกับบทที่ 2 จึงกำหนดค่า git config --global pull.rebase false ไว้ตั้งแต่ต้น การ pull ในสถานการณ์นี้อาจเกิด merge conflict และแก้ไขได้ด้วยวิธีเดียวกับ Lab C ของบทที่ 2
คำถามตรวจความเข้าใจ 3.1: สมาชิก A สั่ง git status แล้วพบข้อความ Your branch is up to date with 'origin/main' แต่สมาชิก B ยืนยันว่าเพิ่ง push งานเข้า main เมื่อ 5 นาทีก่อน อธิบายว่าเหตุใดข้อความของสมาชิก A จึงยังไม่แสดงงานของสมาชิก B และควรสั่งคำสั่งใด
3.2 GitHub flow และ pull request
GitHub flow คือ workflow แบบเบาที่ใช้ branch หลักเพียง branch เดียว (main) ซึ่งต้องอยู่ในสถานะพร้อมใช้งานเสมอ งานทุกชิ้นเกิดบน branch อายุสั้นแล้วรวมกลับผ่าน pull request เอกสารของ GitHub กำหนดขั้นตอนไว้ 6 ขั้น (GitHub Docs: GitHub flow)
- Create a branch สร้าง branch จาก
mainโดยตั้งชื่อตามงาน - Make changes แก้ไขและ commit บน branch นั้น แล้ว push ขึ้น remote
- Create a pull request เปิด pull request เพื่อขอให้รวมงานเข้า
main - Address review comments สมาชิกทีมตรวจทานและให้ความเห็น ผู้เปิดแก้ไขตามความเห็นด้วยการ commit เพิ่มบน branch เดิม
- Merge your pull request เมื่อผ่านการตรวจทานแล้วจึง merge เข้า
main - Delete your branch ลบ branch ที่ใช้เสร็จแล้ว
ขั้นที่ 1–2 คือกติกา Branch-First ของบทที่ 2 ส่วนขั้นที่ 3–6 เพิ่มการตรวจทานโดยผู้อื่นก่อนรวมงาน
pull request คือข้อเสนอให้รวมการเปลี่ยนแปลงเข้าโครงการ เอกสารของ GitHub นิยามว่า "Pull requests are proposals to merge code changes into a project." (GitHub Docs: About pull requests) หน้าของ pull request แบ่งเป็นแท็บหลัก ได้แก่ Conversation สำหรับคำอธิบายและความเห็น Commits สำหรับรายการ commit Files changed สำหรับส่วนต่างของไฟล์ และ Checks ซึ่งแสดงผลของ "automated tests, builds, and other validations" แท็บ Checks จะว่างอยู่จนถึงบทที่ 5 ซึ่งเพิ่มระบบ CI นอกจากนี้ pull request แบบ draft ใช้แสดงงานที่ยังไม่เสร็จ ซึ่ง merge ไม่ได้จนกว่าจะเปลี่ยนสถานะเป็นพร้อมตรวจทาน
- ระดับที่ 1: pull request หนึ่งรายการผูกกับ branch หนึ่ง branch การ commit และ push เพิ่มบน branch เดิมทำให้ pull request อัปเดตเองโดยไม่ต้องเปิดใหม่
- ระดับที่ 2: เมื่อ merge ด้วยวิธี Create a merge commit GitHub สร้าง merge commit ที่มี parent สองตัว ซึ่งให้กราฟแบบเดียวกับ
git merge --no-ffในบทที่ 2 - ระดับที่ 3: หาก
mainเปลี่ยนไปหลังจากเปิด pull request และการเปลี่ยนแปลงทับบริเวณเดียวกัน GitHub จะแจ้งว่า pull request มี conflict ผู้เปิดต้องรวมmainเข้า branch ของตนในเครื่อง แก้ conflict แล้ว push อีกครั้ง
คำถามตรวจความเข้าใจ 3.2: หลังเปิด pull request แล้ว ผู้ตรวจทานขอให้แก้คำผิดใน README หนึ่งจุด ผู้เปิดควรเปิด pull request ใหม่หรือไม่ เพราะเหตุใด
3.3 protected branch: การป้องกัน branch หลัก
GitHub flow กำหนดว่างานต้องผ่านการตรวจทานก่อน merge แต่ตามค่าเริ่มต้น สมาชิกที่มีสิทธิ์เขียนยัง push ตรงเข้า main ได้ protected branch คือการตั้งกฎให้ branch หนึ่งเพื่อบังคับกติกานั้นด้วยระบบ เอกสารของ GitHub ระบุว่ากฎของ protected branch บังคับได้ทั้งจำนวน approving review ที่ต้องมีก่อน merge และเงื่อนไขว่า "all required status checks must pass before collaborators can merge" (GitHub Docs: About protected branches)
| กฎ | ผลต่อทีม | ใช้ในบท |
|---|---|---|
| Require a pull request before merging | ห้าม push ตรง ทุกการเปลี่ยนแปลงต้องผ่าน pull request | 3 |
| Require approvals (จำนวน 1) | ต้องมีสมาชิกอย่างน้อย 1 คนกด Approve ก่อน merge | 3 |
| Require status checks to pass before merging | ต้องให้ CI ผ่านก่อน merge | 5 |
protected branch เป็นการนำหลักให้สิทธิ์เท่าที่จำเป็นจากบทที่ 1 มาใช้กับ repository สมาชิกยังมีสิทธิ์เขียนเพื่อสร้าง branch ของตน แต่ไม่มีสิทธิ์เปลี่ยน main โดยลำพัง
คำถามตรวจความเข้าใจ 3.3: ทีมหนึ่งตั้งกฎ Require approvals จำนวน 1 แต่ไม่ได้เปิด Require a pull request before merging จะเกิดช่องโหว่อะไร
3.4 GitFlow, GitHub flow และ Trunk-Based Development
Git workflow คือข้อตกลงของทีมว่าจะใช้ branch อย่างไร workflow ที่พบบ่อยมีสามแบบ ซึ่งต่างกันที่จำนวนและอายุของ branch
| workflow | โครงสร้าง branch | เหมาะกับ |
|---|---|---|
| GitFlow | branch ถาวรสองตัว (master สำหรับรุ่นที่เผยแพร่ และ develop สำหรับรวมงาน) และ branch ชั่วคราวหลายประเภท ได้แก่ feature, release และ hotfix (Driessen, 2010) | ซอฟต์แวร์ที่ออกรุ่นเป็นรอบและต้องดูแลหลายรุ่นพร้อมกัน |
| GitHub flow | main เพียงตัวเดียว และ branch งานอายุสั้นที่รวมผ่าน pull request | ทีมที่ส่งมอบต่อเนื่องและมีรุ่นที่ใช้งานรุ่นเดียว |
| Trunk-Based Development | ทุกคนรวมงานบน branch เดียว (trunk) บ่อยครั้ง ใช้ branch อายุสั้นมากเพื่อ review และ CI เท่านั้น (Trunk Based Development) | ทีมที่มีระบบทดสอบอัตโนมัติครบและ deploy หลายครั้งต่อวัน |
ผู้คิด GitFlow เขียนหมายเหตุเพิ่มเติมในบทความต้นฉบับเมื่อวันที่ 5 มีนาคม 2020 ว่าทีมที่ทำ continuous delivery ควรใช้ workflow ที่ง่ายกว่า เช่น GitHub flow (Driessen, 2010) งานวิจัยของ DORA สนับสนุนแนวทาง branch อายุสั้นเช่นกัน โดยแนะนำให้มี active branch ไม่เกิน 3 branch แต่ละ branch มีอายุไม่เกินไม่กี่ชั่วโมง และรวมงานเข้า trunk อย่างน้อยวันละครั้ง (DORA: Trunk-based development) รายวิชานี้จึงเลือก GitHub flow ซึ่งเป็นจุดกึ่งกลางระหว่างความเรียบง่ายกับการบังคับ review ผ่าน pull request
คำถามตรวจความเข้าใจ 3.4: ระบุความต่างหลักระหว่าง GitFlow กับ GitHub flow 2 ประการ และเหตุผลที่ผู้คิด GitFlow เองแนะนำ GitHub flow สำหรับทีมที่ทำ continuous delivery
3.5 code review ที่มีคุณภาพ
code review คือการที่สมาชิกทีมตรวจทานการเปลี่ยนแปลงก่อนรวมเข้า main วัตถุประสงค์หลักคือหาข้อผิดพลาดก่อนถึงผู้ใช้ ทำให้มากกว่าหนึ่งคนเข้าใจทุกส่วนของระบบ และรักษามาตรฐานของงานให้สม่ำเสมอ บน GitHub ผู้ตรวจทานเลือกส่ง review ได้สามแบบ ได้แก่ Comment (ให้ความเห็นโดยไม่ตัดสิน) Approve (อนุมัติให้ merge) และ Request changes (ขอให้แก้ก่อน merge)
ความเห็นที่มีคุณภาพมีองค์ประกอบสามส่วน คือ ตำแหน่ง (ไฟล์หรือบรรทัดที่เกี่ยวข้อง) ปัญหา (สิ่งที่ผิดหรือเสี่ยง) และ เหตุผลหรือข้อเสนอ (ผลกระทบและวิธีแก้) ตัวอย่างต่อไปนี้แสดงความเห็นที่ซับซ้อนขึ้นตามลำดับ
- ระดับที่ 1 (ไม่มีสาระ): "ดีแล้ว" ผู้เปิดไม่ได้ข้อมูลใหม่ และไม่มีหลักฐานว่าได้ตรวจจริง
- ระดับที่ 2 (มีตำแหน่งและปัญหา): "README บรรทัด 12 เขียน
/api/itemแต่โค้ดใช้/api/items" - ระดับที่ 3 (มีเหตุผลและข้อเสนอ): ความเห็นระดับที่ 2 ที่เพิ่มว่า "ผู้ใช้ที่อ่าน README จะเรียก endpoint ผิดและได้ 404 เสนอให้แก้เป็น
/api/items"
ประเด็นที่ควรตรวจในรายวิชานี้ ได้แก่ ความถูกต้องตรงกับโค้ดจริง ความครบถ้วนของคำอธิบาย ไฟล์ที่ไม่ควรอยู่ใน repository เช่น .env หรือ node_modules และข้อความ commit ที่สื่อความหมาย ความเห็นต้องมุ่งที่งาน ไม่ใช่ตัวบุคคล
คำถามตรวจความเข้าใจ 3.5: จัดระดับความเห็นต่อไปนี้ตามตัวอย่างข้างต้น และปรับความเห็นระดับต่ำให้เป็นระดับที่ 3: "ไฟล์นี้แปลก ๆ" (ความเห็นต่อ pull request ที่เพิ่มไฟล์ .env เข้ามา)
3.6 กรณีศึกษา: การเลือก Git workflow ให้เหมาะกับทีม
การเลือก workflow ไม่มีคำตอบเดียวที่ถูกเสมอ เกณฑ์ที่ใช้พิจารณา ได้แก่ ความถี่ในการส่งมอบ จำนวนรุ่นที่ต้องดูแลพร้อมกัน ขนาดและประสบการณ์ของทีม และระดับของการทดสอบอัตโนมัติ กรณีศึกษาสองสถานการณ์ต่อไปนี้ใช้ฝึกผลลัพธ์การเรียนรู้ 3.2 และเป็นโจทย์ของงานข้อ 3
สถานการณ์ที่ 1: ทีม 3 คนพัฒนาเว็บ API ของร้านค้าออนไลน์ซึ่งมีรุ่นที่ใช้งานจริงรุ่นเดียว ทีมต้องการ deploy การแก้ไขเล็ก ๆ ได้หลายครั้งต่อสัปดาห์ และมี unit test ครอบคลุม endpoint หลัก
สถานการณ์ที่ 2: ทีม 8 คนพัฒนาแอปพลิเคชันสำหรับติดตั้งในเครื่องของโรงพยาบาล ออกรุ่นใหม่ทุก 6 เดือน และต้องส่งการแก้ไขด้านความปลอดภัยให้โรงพยาบาลที่ยังใช้รุ่นก่อนหน้าอีก 2 รุ่น
สำหรับแต่ละสถานการณ์ ให้เลือก workflow อธิบายลำดับการทำงานของ branch และให้เหตุผลที่โยงกับบริบทของทีม การเทียบทางเลือกอย่างน้อย 2 ทางพร้อมข้อแลกเปลี่ยนคือเกณฑ์ของระดับดี
3.7 เส้นทางของการเปลี่ยนแปลงจากเครื่องหนึ่งสู่ทีม
การมี remote repository ทำให้แลกเปลี่ยน commit ได้ แต่ไม่ได้ทำให้ไฟล์ในทุกเครื่องตรงกันทันที สมมติว่าเพื่อนร่วมทีม merge งานบน GitHub แล้ว เครื่องที่ยังไม่ fetch จะยังอ้างอิงข้อมูล remote ตามที่ทราบครั้งก่อน การวิเคราะห์จึงต้องแยก branch ในเครื่อง เช่น main ออกจาก remote-tracking branch เช่น origin/main และแยกทั้งสองออกจากสถานะที่อยู่บนเซิร์ฟเวอร์จริง
ตัวอย่างสถานการณ์สมมติของทีมสามคนเริ่มจากทุกคนมี commit A สมาชิกคนแรกเพิ่ม B และ merge บน GitHub สมาชิกคนที่สองยังอยู่ A แล้วเพิ่ม C ในเครื่อง หาก push โดยคิดว่า “ทำคนละไฟล์จึงไม่ต้องอัปเดต” อาจถูกปฏิเสธเพราะปลายทางมีประวัติที่เครื่องยังไม่ได้รวม การปฏิเสธนี้ไม่ใช่การสูญหายของงาน C แต่เป็นสัญญาณว่าต้องรับรู้ B และรวมประวัติตามข้อตกลงทีมก่อน
ลำดับตรวจที่ปลอดภัยในบริบทของบทนี้คืออ่าน git status, เรียก git fetch origin แล้วดูกราฟทุก branch เพื่อระบุความสัมพันธ์ก่อนตัดสินใจ การ fetch นำข้อมูลมาให้ตรวจโดยยังไม่รวมเข้ากับ branch ปัจจุบัน ส่วน pull รวมขั้นรับข้อมูลกับการบูรณาการตามค่าตั้ง จึงไม่ควรใช้สองคำนี้แทนกันโดยไม่อธิบายผล ความชัดเจนของสถานะสำคัญกว่าการจำคำสั่งให้สั้นที่สุด
เมื่อรวม B กับ C แล้วต้องทดสอบผลรวมอีกครั้ง แม้แต่ละงานเคยผ่าน test ของตนเอง เพราะการทำงานร่วมกันอาจเปลี่ยนพฤติกรรม ตัวอย่างเช่น B เปลี่ยนชื่อฟิลด์ใน /health ขณะที่ C เพิ่มสคริปต์ตรวจชื่อเดิม ทั้งสองฝั่งดูถูกต้องเมื่อแยกกัน แต่ผลรวมใช้ไม่ได้ กรณีนี้เชื่อมกับ conflict ทางความหมายในบทที่ 2 และเป็นเหตุผลที่ CI ต้องตรวจ snapshot ของงานที่กำลังจะรวม
GitHub flow กำหนดวงจรสร้าง branch เปลี่ยนแปลง เปิด pull request รับความเห็น และ merge หลังผ่านเงื่อนไข โดยเก็บบริบทของการตัดสินใจไว้ใน pull request หลักการนี้ช่วยให้ทีมอธิบายได้ว่างานหนึ่งเข้าสู่ branch หลักด้วยเหตุผลใด (GitHub Docs: GitHub flow)
3.8 pull request เป็นข้อเสนอที่มีหลักฐาน
pull request ที่ตรวจง่ายควรเริ่มจากปัญหาที่สังเกตได้ แล้วแสดงพฤติกรรมหลังแก้ ตัวอย่างข้อความ “ปรับ health” ยังไม่เพียงพอ เพราะ reviewer ไม่ทราบข้อบกพร่องเดิม ขอบเขต หรือวิธีทดสอบ ข้อเสนอที่ชัดกว่าอธิบายว่า “สคริปต์ตรวจถือว่า HTTP 500 เป็นผลสำเร็จ จึงเพิ่มเงื่อนไขให้คืนสถานะไม่เป็นศูนย์ และทดสอบทั้งกรณี 200 กับ 500” ข้อความนี้เชื่อมปัญหา การแก้ และหลักฐานไว้ด้วยกัน
ข้อมูลสมมติสำหรับ PR หนึ่งรายการอาจมีเงื่อนไขดังนี้: endpoint ปกติคืน 200 เมื่อแอปพร้อม สคริปต์ต้องสำเร็จเมื่อได้ 200 และต้องล้มเมื่อไม่ได้ตามเงื่อนไข การตรวจควรแยกกรณีตอบ 500 กรณีเชื่อมต่อไม่ได้ และกรณีใช้ URL ผิด เพราะอาการเหล่านี้เกิดคนละชั้น หากแสดงเฉพาะกรณีปกติจะยังไม่พิสูจน์ว่าประตูตรวจสามารถหยุดความผิดพลาดได้
การทดสอบเชิงลบหรือ negative test จึงมีบทบาทสำคัญ ตัวอย่างเช่น เปลี่ยนค่าให้สคริปต์เรียกพอร์ตที่ไม่มีบริการในสภาพแวดล้อมทดลอง แล้วบันทึกว่าสถานะไม่เป็นศูนย์จริง การคืนค่าหลังทดลองต้องอยู่ใน checklist ด้วย มิฉะนั้นการพิสูจน์กรณีล้มอาจกลายเป็นค่าที่ถูก merge โดยไม่ตั้งใจ หลักฐานที่ดีควรระบุว่าใช้ snapshot ใดและค่าทดสอบใด ไม่ใช้ภาพหน้าจอสีเขียวที่ไม่เห็นบริบท
ขอบเขต PR ควรสัมพันธ์กับคำถามที่ต้องตัดสิน สมมติว่าใน PR เดียวมีการแก้ healthcheck เปลี่ยนชื่อไฟล์ทั้งหมด และเปลี่ยนรูปแบบโค้ดจำนวนมาก reviewer ต้องแยกความต่างเชิงพฤติกรรมออกจากความต่างเชิงรูปแบบ ทำให้ตรวจจุดผิดพลาดได้ยากขึ้น การแยกงานที่ไม่พึ่งกันทำให้ย้อนกลับเฉพาะส่วนได้ง่าย แต่ไม่ควรแยกโค้ดกับ test ที่จำเป็นต่อกันจนแต่ละ PR อยู่ในสภาพใช้ไม่ได้
3.9 การให้ความเห็นที่นำไปปรับงานได้
ความเห็น review ที่ดีมีจุดอ้างอิง เหตุผล ผลกระทบ และเงื่อนไขที่ทำให้ยอมรับได้ ตัวอย่าง “ตรงนี้ไม่ดี” ไม่บอกทางแก้ ขณะที่ “คำสั่งนี้คืน 0 หลัง curl ล้ม ทำให้ pipeline ผ่านทั้งที่ปลายทางไม่ตอบ ควรเก็บสถานะเดิมและเพิ่มกรณีทดสอบเชื่อมต่อไม่ได้” ทำให้ผู้เขียนตรวจข้อกล่าวอ้างและเสนอวิธีแก้ที่เทียบเท่ากันได้
ตัวอย่างอีกคู่คือ “ใช้ชื่อให้ดีกว่านี้” เทียบกับ “ตัวแปร time ใช้เก็บมิลลิวินาที แต่ใน log แสดงหน่วยวินาที ชื่อ durationMs และการแปลงหน่วยในจุดแสดงผลจะช่วยลดการอ่านผิด” ความเห็นหลังระบุความกำกวมที่มีผลต่อการใช้งาน ส่วนการชอบชื่อใดเป็นการส่วนตัวควรแยกจากเงื่อนไขที่ต้องแก้ก่อน merge เพื่อไม่ให้รายละเอียดเล็กน้อยบังข้อผิดพลาดที่สำคัญกว่า
reviewer ควรตรวจความสอดคล้องกับข้อกำหนดก่อนรูปแบบ เช่น endpoint ต้องไม่ส่งรหัสผ่านใน response ต้องคืนสถานะถูกต้อง และ test ต้องครอบคลุมกรณีที่รายงานว่าผิด จากนั้นจึงดูความอ่านง่ายและโอกาสลดความซับซ้อน การจัดลำดับแบบนี้ช่วยให้เวลาที่มีจำกัดถูกใช้กับผลกระทบจริง ขณะเดียวกันผู้เขียนควรตอบแต่ละประเด็นว่าปรับแล้ว มีหลักฐานใด หรือมีเหตุผลใดที่เลือกวิธีอื่น
การกด resolve ไม่ได้พิสูจน์ว่าข้อเสนอได้รับการแก้ reviewer ต้องตรวจ diff ล่าสุดและผลทดสอบหลังแก้ โดยเฉพาะเมื่อมี commit ใหม่ที่เปลี่ยนบริเวณซึ่งเคยอนุมัติแล้ว ในทางกลับกันการคัดค้านโดยไม่ระบุผลกระทบก็ทำให้กระบวนการหยุดโดยไม่มีเกณฑ์สิ้นสุด ทีมจึงควรตกลงประเภทความเห็นและเกณฑ์พร้อม merge ให้ชัดตั้งแต่ต้น
3.10 กติกาที่ป้องกันความผิดพลาดและข้อจำกัดของกติกา
การป้องกัน branch หลักช่วยบังคับเงื่อนไขก่อนรวมงาน เช่น การอนุมัติหรือ required checks แต่ผลที่ได้ขึ้นกับกติกาที่ตั้งและสิทธิ์ของผู้ใช้ จึงต้องทดลองทั้งกรณีผ่านและกรณีถูกปฏิเสธใน repository ฝึก ไม่ควรสรุปว่ากติกาทำงานเพราะเห็นสวิตช์เปิดอยู่ การตรวจควรระบุ branch เป้าหมาย บัญชีที่ใช้ และเงื่อนไขที่ขาด แล้วเปรียบเทียบกับผลจริง
ตัวอย่างสถานการณ์คือทีมตั้งให้ต้องมีหนึ่ง approving review แต่เลือก required check คนละชื่อกับ job ที่ workflow สร้าง ผลอาจเป็นการรอ check ที่ไม่ปรากฏ แม้ test จริงผ่านแล้ว วิธีแก้เริ่มจากอ่านชื่อ check จาก run ที่เกิดจริงและตรวจการจับคู่กติกา ไม่ใช่ปิดการป้องกันทั้งหมดเพื่อให้ merge ได้ กรณีนี้เชื่อมกับบทที่ 5 ซึ่งจะสร้างชื่อ job ให้คงที่และอธิบายสถานะของ workflow
อีกสถานการณ์คือผู้เขียนเป็นคนเดียวที่รู้วิธีรันระบบ ถ้า PR ได้อนุมัติจากการอ่านโค้ดอย่างเดียว ทีมยังเสี่ยงต่อการพึ่งบุคคล การให้ reviewer ทดลองจาก clone ใหม่ตามคู่มือช่วยตรวจว่าความรู้สำคัญอยู่ใน repository จริงหรือไม่ หากต้องถามขั้นตอนที่เอกสารไม่มี ควรบันทึกขั้นนั้นกลับลงคู่มือเพื่อให้การ review ครั้งต่อไปทำซ้ำได้
การเลือก workflow ต้องสัมพันธ์กับวงจรปล่อยรุ่น ทีมเล็กที่ส่งบริการเดียวบ่อยอาจใช้ branch อายุสั้นกับ main ที่พร้อมส่งมอบ ส่วนระบบที่ต้องดูแลหลายรุ่นพร้อมกันต้องมีนโยบายแก้ย้อนหลังเพิ่มเติม ชื่อ GitFlow หรือ Trunk-Based Development ไม่ได้รับประกันผลสำเร็จ สิ่งที่ต้องอธิบายคือการเปลี่ยนหนึ่งรายการรอที่ใด รวมกับงานอื่นเมื่อใด ตรวจผลรวมอย่างไร และกู้คืนอย่างไรเมื่อผิดพลาด
หลักฐานขั้นต่ำเมื่อจบบทนี้จึงไม่ใช่เพียง URL ของ repository แต่เป็นตัวอย่าง PR ที่มีปัญหาและผลหลังแก้ มีความเห็น review ที่ตรวจได้ มีการตอบกลับด้วยหลักฐาน และมี commit ที่รวมเข้ากับ branch หลักแล้ว ข้อมูลเหล่านี้จะต่อเป็นเส้นทางตรวจสอบตั้งแต่ Git ไปจนถึง deployment ในบทถัดไป
ตัวอย่างที่ไม่ถูกต้องและวิธีตรวจแก้
| วิธีที่ไม่ถูกต้อง | ผลที่อาจเกิด | การแก้ที่มีหลักฐาน |
|---|---|---|
| เห็น PR ไม่มี conflict จึง merge โดยไม่อ่าน diff | conflict ทางความหมาย เช่นโค้ดกับ healthcheck ใช้พอร์ตต่างกันหลุดผ่าน | อ่านข้อกำหนดและ diff พร้อมตรวจผลรวมด้วย test |
| approving review ก่อน commit ใหม่แล้วคิดว่าครอบคลุมทุกงานภายหลัง | โค้ดที่อนุมัติกับโค้ดที่ merge อาจต่างกัน | ตรวจ diff ล่าสุดและกติกาการคงหรือยกเลิก approval ของ repository |
| reviewer บอกเพียงว่าไม่ชอบวิธีเขียน | ผู้เขียนไม่ทราบผลกระทบหรือเกณฑ์ยอมรับ | ระบุจุดที่มีปัญหา เงื่อนไขที่ทำให้เกิด ผลกระทบ และข้อเสนอที่ตรวจได้ |
| ปิด branch protection ทุกครั้งที่ check รอไม่จบ | ถอนประตูทั้งหมดทั้งที่อาจเป็นเพียงชื่อ check หรือ trigger ไม่ตรง | ตรวจ run จริง ชื่อ check และนโยบาย แล้วแก้เงื่อนไขที่ผิดเฉพาะจุด |
การ review ไม่ได้กำหนดว่าทุกข้อเสนอของ reviewer ต้องถูกยอมรับ หากมีวิธีอื่นที่ตอบข้อกำหนดและมีหลักฐานเทียบได้ ผู้เขียนสามารถอธิบายเหตุผลได้ เป้าหมายคือข้อสรุปที่ตรวจสอบได้ร่วมกัน ไม่ใช่การใช้สิทธิ์อนุมัติแทนเหตุผลทางเทคนิค
ปฏิบัติการที่ 3 การทำงานเป็นทีมบน GitHub
ปฏิบัติการนี้ประกอบด้วย Lab A–D ซึ่งทำเป็นทีมละ 3 คน บทบาทในแต่ละ Lab ระบุไว้ที่หัวข้อย่อย (หัวหน้าทีม หรือสมาชิกทุกคน) แต่ละ Lab แบ่งเป็นสองส่วน ส่วน ฝึกตามตัวอย่าง ให้พิมพ์คำสั่งตามและเทียบผลกับตัวอย่าง ส่วน ตัดสินใจเอง (A.4, B.3, C.4 และ D.4) ไม่มีคำสั่งกำกับ ผู้เรียนต้องเลือกคำสั่งหรือตัดสินใจด้วยตนเอง
ผลลัพธ์ในบทนี้ได้จากการทดสอบกับ remote ที่จำลองด้วย bare repository ในเครื่อง URL ในผลลัพธ์จึงเป็น path ในเครื่อง (เช่น /tmp/remotes/devops-app.git) เมื่อใช้ GitHub จริง URL จะเป็น https://github.com/ชื่อบัญชี/ชื่อ repository.git และมีบรรทัดความคืบหน้าและข้อความ remote: เพิ่มขึ้น เลข hash และชื่อผู้ใช้ต่างกันในแต่ละเครื่อง
personal access token ที่ใช้แทนรหัสผ่านตอน push มีสิทธิ์เท่ากับบัญชีของผู้เรียนตามขอบเขตที่เลือก ห้ามคัดลอกลงในไฟล์ใดของ repository ห้ามส่งในแชตกลุ่ม และควรกำหนดวันหมดอายุไม่เกินวันสิ้นภาคการศึกษา
Lab A: repository เดี่ยวขึ้น GitHub และ repository ทีม
สถานการณ์: repository devops-lab01 จากบทที่ 2 ยังอยู่บนเครื่องของผู้เรียนเพียงเครื่องเดียว และทีมยังไม่มีที่รวมงานร่วมกัน
เป้าหมาย: ส่ง repository เดี่ยวขึ้น GitHub (เตรียมพื้น) และสร้าง repository ทีมจากแอปตั้งต้น (ส่วนต้นของ LLO 3.1)
ฝึกตามตัวอย่าง
A.1 เตรียมการยืนยันตัวตนกับ GitHub (สมาชิกทุกคน)
- สร้าง personal access token ที่หน้า Settings → Developer settings → Personal access tokens ของบัญชี GitHub กำหนดวันหมดอายุ และเลือกสิทธิ์เฉพาะการอ่านและเขียน repository เก็บ token ไว้ในที่ปลอดภัย เพราะหน้าเว็บแสดง token เพียงครั้งเดียว
- กำหนดให้
git pullรวมงานด้วย merge ตามหัวข้อ 3.1
git config --global pull.rebase falseเมื่อ Git ถามรหัสผ่านตอน push ให้ใส่ token แทนรหัสผ่านของบัญชี
A.2 ส่ง repository เดี่ยวขึ้น GitHub (สมาชิกทุกคน)
สร้าง repository ใหม่บน GitHub ชื่อ devops-lab01 แบบว่าง โดยไม่เลือกสร้าง README, .gitignore หรือ license เพราะประวัติทั้งหมดมีอยู่แล้วในเครื่อง จากนั้นผูก remote และ push ทั้ง branch และ tag
cd ~/devops-lab01
git remote add origin https://github.com/ชื่อบัญชี/devops-lab01.git
git remote -v
git push -u origin main
git push origin --tags
git statusorigin /tmp/remotes/devops-lab01.git (fetch)
origin /tmp/remotes/devops-lab01.git (push)
To /tmp/remotes/devops-lab01.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
To /tmp/remotes/devops-lab01.git
* [new tag] v0.1.0 -> v0.1.0
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree cleanบรรทัด branch 'main' set up to track 'origin/main' คือผลของตัวเลือก -u และบรรทัด [new tag] ยืนยันว่า tag v0.1.0 (M1) ถูกส่งขึ้นแล้ว
A.3 สร้าง repository ทีมจากแอปตั้งต้น (หัวหน้าทีม)
แอปตั้งต้นที่ผู้สอนแจกมีโครงสร้างดังนี้
devops-app/
├── .gitignore
├── README.md
├── package.json
├── scripts/check-errors.sh
├── src/app.js
├── src/server.js
└── test/app.test.jsแอปเป็นเว็บ API ที่เขียนด้วย Node.js และ Express มี endpoint /, /health และ /api/items โดย scripts/check-errors.sh คือสคริปต์ฉบับแก้แล้วจาก Lab E ของบทที่ 1 ผู้เรียนไม่ต้องแก้โค้ดของแอป งานในบทถัด ๆ ไปคือการเพิ่มชั้น DevOps รอบแอปนี้
หัวหน้าทีมสร้าง repository ว่างบน GitHub ชื่อ devops-app แบบ public แล้ว push แอปตั้งต้นขึ้นเป็น commit แรก
cd ~/devops-app
git init
git add .
git commit -m "แอปตั้งต้นจากผู้สอน"
git remote add origin https://github.com/ชื่อบัญชีหัวหน้าทีม/devops-app.git
git push -u origin mainจากนั้นเชิญสมาชิกที่หน้า Settings → Collaborators ของ repository สมาชิกต้องกดยอมรับคำเชิญจากอีเมลหรือหน้าแจ้งเตือนของ GitHub จึงจะ push ได้
ก่อนเปิด branch protection ใน Lab B หัวหน้าทีมเพิ่มไฟล์ template ของ pull request เข้า main โดยตรง ไฟล์ชื่อ .github/pull_request_template.md ทำให้ GitHub เติมข้อความนี้ลงในช่องคำอธิบายเมื่อสมาชิกเปิด pull request ใหม่ ทุก pull request ของทีมจึงตอบคำถามชุดเดียวกัน และผู้ตรวจทานรู้ว่าต้องตรวจอะไร
mkdir -p .github
nano .github/pull_request_template.md## สิ่งที่เปลี่ยน
-
## เหตุผล
-
## วิธีทดสอบ
- [ ] รัน `npm test` ผ่านบนเครื่องของตนเอง (ตั้งแต่บทที่ 4)
- [ ] ระบุคำสั่งหรือขั้นตอนที่ผู้ตรวจทานใช้ตรวจได้
## Checklist
- [ ] ไม่มีรหัสผ่าน ค่าลับ หรือไฟล์ `.env` ใน pull request นี้
- [ ] ชื่อ branch และข้อความ commit สื่อความหมาย
- [ ] เชื่อมกับ issue ที่เกี่ยวข้อง (ถ้ามี)git add .github/pull_request_template.md
git commit -m "เพิ่ม template ของ pull request"
git pushขั้นนี้ทำก่อน Lab B เพราะเมื่อเปิด branch protection แล้ว การเพิ่มไฟล์เข้า main ต้องผ่าน pull request ทีมสามารถแก้ checklist ภายหลังได้ผ่าน pull request ตามปกติ
A.4 clone repository ทีม (สมาชิกทุกคน)
cd ~
git clone https://github.com/ชื่อบัญชีหัวหน้าทีม/devops-app.git
cd devops-app
git log --onelineCloning into 'devops-app'...
done.ตัดสินใจเอง A.5 (เตรียมพื้น): ยืนยันจากเครื่องของตนเองโดยไม่เปิดหน้าเว็บว่า remote ของ devops-lab01 มี tag v0.1.0 แล้ว เลือกคำสั่งเองจากเอกสาร git-ls-remote และอธิบายว่าเหตุใดผลจึงมี tag ชื่อเดียวกันสองบรรทัด
ผลลัพธ์ที่คาดหวัง A.5: ผลแสดง refs/tags/v0.1.0 และ refs/tags/v0.1.0^{} พร้อม hash คนละค่า
จุดตรวจ A: devops-lab01 บน GitHub แสดงประวัติ commit จากบทที่ 2 และ tag v0.1.0 · repository ทีมมีไฟล์ .github/pull_request_template.md บน main · สมาชิกทุกคนมีโฟลเดอร์ ~/devops-app ที่ clone มาจาก repository ทีม
ปัญหาที่พบบ่อย
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| push แล้วขึ้นข้อความว่ารหัสผ่านใช้ไม่ได้ (authentication failed) | ใส่รหัสผ่านของบัญชีแทน token | ใส่ personal access token เมื่อ Git ถามรหัสผ่าน |
push ครั้งแรกถูกปฏิเสธด้วยข้อความ rejected และ fetch first | สร้าง repository บน GitHub พร้อม README ทำให้ remote มี commit ที่เครื่องไม่มี | สร้าง repository ใหม่แบบว่าง หรือ git pull origin main ก่อนแล้วแก้ conflict |
remote origin already exists | เคยสั่ง git remote add ไปแล้ว | ตรวจด้วย git remote -v และแก้ URL ด้วย git remote set-url origin URL |
| สมาชิก push repository ทีมไม่ได้ (403 หรือ permission denied) | ยังไม่ได้กดยอมรับคำเชิญ | เปิดคำเชิญจากอีเมลหรือหน้าแจ้งเตือนแล้วกดยอมรับ |
git push ไม่ส่ง tag | tag ต้องส่งแยกจาก branch | สั่ง git push origin --tags |
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
Lab B: branch protection
สถานการณ์: สมาชิกทุกคนมีสิทธิ์เขียน repository ทีม หากมีผู้ push ตรงเข้า main โดยไม่ผ่านการตรวจทาน ทีมจะไม่มีหลักฐานว่างานนั้นถูกตรวจ
เป้าหมาย: LLO 3.1 ตั้ง branch protection ของ main ใน repository ทีม
ฝึกตามตัวอย่าง
B.1 ตั้งกฎของ main (หัวหน้าทีม) เปิด Settings → Branches ของ repository ทีม แล้วเพิ่มกฎสำหรับ branch ชื่อ main โดยเปิดตัวเลือกต่อไปนี้
- Require a pull request before merging
- Require approvals และกำหนดจำนวนเป็น 1
บันทึกกฎและถ่ายภาพหน้าตั้งค่าไว้เป็นหลักฐานงานข้อ 1 หน้าตั้งค่าของ GitHub บางบัญชีแสดงเป็น Rulesets แทน Branch protection rules ให้เลือกกำหนดเป้าหมายเป็น branch main และเปิดตัวเลือกที่มีความหมายเดียวกัน
B.2 ทดสอบกฎด้วยการสาธิต (หัวหน้าทีม) ยังไม่ต้องลอง push ตรงจนถึง B.3 ให้ทุกคนดูหน้า Branches ว่า main มีสัญลักษณ์ว่าเป็น protected branch
ตัดสินใจเอง B.3 (LLO 3.1): สมาชิกคนหนึ่งในทีมทดลองแก้ README บน main ในเครื่อง commit แล้ว push ตรงเข้า main บันทึกข้อความที่ได้ จากนั้นตัดสินใจว่าจะนำงานนั้นเข้า main อย่างถูกต้องได้อย่างไรโดยไม่สูญเสีย commit ที่ทำไว้ และทำให้ main ในเครื่องกลับมาตรงกับ origin/main
ผลลัพธ์ที่คาดหวัง B.3: push ตรงถูกปฏิเสธด้วยข้อความที่ขึ้นต้นด้วย remote: และระบุว่า branch ถูกป้องกัน commit ถูกย้ายไปอยู่บน branch ใหม่ที่ push ขึ้นได้ และ git status บน main แสดงว่าตรงกับ origin/main
ปัญหาที่พบบ่อย
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| ไม่พบเมนู Branches ใน Settings | ผู้ที่เปิดหน้าไม่ใช่เจ้าของ repository | ให้หัวหน้าทีม (เจ้าของ) ตั้งค่า |
| หน้าตั้งค่าแจ้งว่ากฎยังไม่มีผล | repository เป็นแบบ private บนบัญชีที่ไม่รองรับ | เปลี่ยน repository เป็นแบบ public ตามข้อกำหนดของรายวิชา |
| push ตรงยังผ่านได้ | สะกดชื่อ branch ในกฎผิด หรือไม่ได้เปิด Require a pull request before merging | ตรวจชื่อ branch ในกฎว่าเป็น main และตัวเลือกถูกเปิด |
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
Lab C: ทุกคนเปิด pull request
สถานการณ์: README ของแอปตั้งต้นมีหัวข้อ "สมาชิกทีม" ที่ยังว่าง สมาชิกทุกคนต้องเพิ่มชื่อและบทบาทของตน ตามกติกา GitHub flow งานของแต่ละคนต้องเข้า main ผ่าน pull request
เป้าหมาย: LLO 3.1 ทำงานตาม GitHub flow ขั้นที่ 1–3 และแก้ conflict ที่เกิดจากงานของสมาชิกหลายคน
ฝึกตามตัวอย่าง
C.1 สร้าง branch แก้ไข และ push (สมาชิกทุกคน) ตั้งชื่อ branch ตามรูปแบบ docs/add-ชื่อ แล้วเพิ่มบรรทัดชื่อของตนต่อท้ายหัวข้อ "สมาชิกทีม" ใน README
cd ~/devops-app
git switch -c docs/add-alice
echo "- alice" >> README.md
git add README.md
git commit -m "เพิ่มชื่อ alice ใน README"
git push -u origin docs/add-aliceSwitched to a new branch 'docs/add-alice'
[docs/add-alice 12de416] เพิ่มชื่อ alice ใน README
1 file changed, 1 insertion(+)
To /tmp/remotes/devops-app.git
* [new branch] docs/add-alice -> docs/add-alice
branch 'docs/add-alice' set up to track 'origin/docs/add-alice'.C.2 เปิด pull request บน GitHub (สมาชิกทุกคน) เปิดหน้า repository ทีม GitHub จะแสดงแถบแนะนำให้เปิด pull request จาก branch ที่เพิ่ง push ให้ตรวจว่า base คือ main และ compare คือ branch ของตน ตั้งชื่อ pull request ให้บอกสิ่งที่เปลี่ยน และเขียนคำอธิบายอย่างน้อยสองบรรทัด คือ สิ่งที่เปลี่ยนและวิธีตรวจ จากนั้นเลือกสมาชิกอย่างน้อย 1 คนเป็นผู้ตรวจทาน (Reviewers)
C.3 พบ conflict หลังจาก pull request แรก merge แล้ว เมื่อ pull request ของสมาชิกคนแรกถูก merge ใน Lab D pull request ของคนอื่นที่เพิ่มบรรทัดในตำแหน่งเดียวกันจะมี conflict เพราะทุกคนต่อท้ายบรรทัดเดียวกันของ README ผู้เปิด pull request ที่มี conflict ต้องรวม main ล่าสุดเข้า branch ของตนในเครื่อง
git switch docs/add-bob
git pull origin mainFrom /tmp/remotes/devops-app
* branch main -> FETCH_HEAD
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.## สมาชิกทีม
<<<<<<< HEAD
- bob
=======
- alice
>>>>>>> 0ff2db5b013477ebb0260df24ef307cfcf5773c3ส่วนล่างของ conflict แสดงเป็นเลข hash แทนชื่อ branch เพราะ git pull origin main รวมงานจาก commit ที่ดึงมาโดยตรง ความหมายของเครื่องหมายเหมือนบทที่ 2 ทุกประการ
ตัดสินใจเอง C.4 (LLO 3.1): แก้ conflict ให้หัวข้อ "สมาชิกทีม" มีชื่อของทุกคนที่ merge แล้วรวมกับชื่อของตนเอง ตรวจว่าไม่มีเครื่องหมาย conflict เหลือ ปิดการ merge ด้วย commit แล้ว push branch เดิม จากนั้นตรวจบนหน้า pull request ว่าข้อความแจ้ง conflict หายไป
ผลลัพธ์ที่คาดหวัง C.4: grep ไม่พบเครื่องหมาย conflict (exit 1) pull request ไม่แสดง conflict และกราฟของ branch มี merge commit ที่รวม main เข้ามา
ปัญหาที่พบบ่อย
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
fatal: Need to specify how to reconcile divergent branches. | ยังไม่ได้กำหนด pull.rebase (ทดสอบแล้วว่าเกิดกับ Git 2.43.0) | สั่ง git config --global pull.rebase false ตาม A.1 แล้ว pull ใหม่ |
| ไม่พบแถบแนะนำให้เปิด pull request | push branch ไปแล้วนาน หรือ push ไม่สำเร็จ | เปิดแท็บ Pull requests แล้วกด New pull request และเลือก branch เอง |
| pull request แสดงไฟล์ที่ไม่เกี่ยวข้องจำนวนมาก | สร้าง branch จาก branch อื่นแทน main | ตรวจ base และ compare ให้ถูก หรือสร้าง branch ใหม่จาก main ล่าสุด |
| แก้ conflict แล้ว pull request ยังแจ้ง conflict | ยังไม่ได้ commit หรือยังไม่ได้ push | ตรวจด้วย git status แล้ว commit และ git push |
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
Lab D: review และ merge
สถานการณ์: pull request ของทุกคนรอการตรวจทาน branch protection ไม่อนุญาตให้ merge จนกว่าจะมีผู้กด Approve อย่างน้อย 1 คน
เป้าหมาย: LLO 3.1 ทำงานตาม GitHub flow ขั้นที่ 4–6 และ LLO 3.3 ให้ความเห็นด้านคุณภาพ
ฝึกตามตัวอย่าง
D.1 ตรวจทาน pull request ของสมาชิก (ผู้ตรวจทาน) เปิดแท็บ Files changed ของ pull request ที่ได้รับมอบหมาย อ่านส่วนต่างของไฟล์ทีละบรรทัด กดเครื่องหมาย + ข้างบรรทัดที่ต้องการให้ความเห็น เขียนความเห็นตามองค์ประกอบในหัวข้อ 3.5 แล้วกด Review changes และเลือก Comment, Approve หรือ Request changes
D.2 แก้ไขตามความเห็น (ผู้เปิด pull request) แก้ไขบน branch เดิมในเครื่อง commit และ push pull request จะแสดง commit ใหม่ต่อจากความเห็นเดิม ตอบกลับความเห็นว่าแก้แล้วอย่างไร
D.3 merge และลบ branch (ผู้เปิด pull request) เมื่อได้ Approve แล้ว เลือกวิธี Create a merge commit แล้วกด Merge pull request และกด Delete branch จากนั้นปรับเครื่องของตนให้ตรงกับ remote
git switch main
git pull
git branch -d docs/add-alice
git fetch --prune
git branch -aSwitched to branch 'main'
Your branch is up to date with 'origin/main'.
From /tmp/remotes/devops-app
e1c8c79..5cd2cb2 main -> origin/main
Updating e1c8c79..5cd2cb2
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
Deleted branch docs/add-alice (was 12de416).
From /tmp/remotes/devops-app
- [deleted] (none) -> origin/docs/add-alice
* main
remotes/origin/HEAD -> origin/main
remotes/origin/mainข้อความ Your branch is up to date บรรทัดที่สองยังเป็นข้อมูลก่อน pull (หัวข้อ 3.1) git pull ครั้งนี้เป็น fast-forward เพราะ main ในเครื่องไม่มี commit ใหม่ของตนเอง ส่วน git fetch --prune ลบตัวชี้ origin/docs/add-alice ที่ไม่มีอยู่บน remote แล้ว
ตัดสินใจเอง D.4 (LLO 3.3): สมาชิกแต่ละคนต้องให้ความเห็นด้านคุณภาพใน pull request ของสมาชิกอย่างน้อย 1 รายการ ความเห็นต้องระบุตำแหน่ง ปัญหา และเหตุผลหรือข้อเสนอ ตามหัวข้อ 3.5 หาก pull request ไม่มีข้อผิดพลาด ให้เลือกประเด็นด้านความชัดเจนของข้อความ commit หรือคำอธิบายของ pull request แล้วตัดสินใจว่าจะส่งเป็น Comment, Approve หรือ Request changes พร้อมเหตุผลของการตัดสินใจนั้น
ผลลัพธ์ที่คาดหวัง D.4: ทุกคนมีความเห็นอย่างน้อย 1 รายการที่ระบุบรรทัดและเหตุผล ทุก pull request ถูก merge ผ่าน review และกราฟของ main มี merge commit เท่ากับจำนวนสมาชิก
ปัญหาที่พบบ่อย
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| ปุ่ม Merge pull request กดไม่ได้ | ยังไม่มี Approve ตามกฎ หรือมี conflict | ขอให้ผู้ตรวจทานกด Approve หรือแก้ conflict ตาม C.4 |
| ผู้เปิดกด Approve pull request ของตนเองไม่ได้ | GitHub ไม่นับ approval จากผู้เปิด pull request | ให้สมาชิกคนอื่นเป็นผู้ตรวจทาน |
git branch -d ขึ้นข้อความว่า branch ยังไม่ถูก merge | ยังไม่ได้ git pull บน main หลัง merge บนเว็บ | สั่ง git pull บน main ก่อนลบ branch |
| กราฟไม่มี merge commit | เลือกวิธี Squash and merge หรือ Rebase and merge | ใช้ Create a merge commit ตามข้อตกลงของรายวิชา |
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
เก็บกวาดเมื่อจบปฏิบัติการ
ปฏิบัติการในบทนี้ไม่มีทรัพยากรที่ต้องลบ ให้ตรวจสถานะส่งมอบดังนี้ main ในเครื่องของทุกคนตรงกับ origin/main (git pull แล้ว git status แสดงว่า up to date) ไม่มี branch งานค้างทั้งในเครื่องและบน remote (git branch -a) และ branch protection ของ main ยังเปิดอยู่ เก็บ repository devops-app และ devops-lab01 ไว้ เพราะบทที่ 4 ทำงานต่อบน repository ทีม หาก token ใดเคยถูกคัดลอกไปไว้ในที่ไม่ปลอดภัย ให้ลบ token นั้นที่หน้า Personal access tokens แล้วสร้างใหม่
สรุป
การทำงานเป็นทีมด้วย Git อาศัย remote repository ที่ทีมตกลงให้เป็นแหล่งความจริงเดียว คำสั่ง git push ส่ง commit ขึ้น remote คำสั่ง git fetch ดึงข้อมูลใหม่มาโดยไม่แก้ไขงานในเครื่อง และ git pull ดึงแล้วรวมเข้ากับ branch ปัจจุบัน ข้อมูล origin/main ในเครื่องเป็นภาพจากการดึงครั้งล่าสุดเท่านั้น และเมื่อสองฝั่งมี commit ใหม่ Git รุ่นปัจจุบันต้องได้รับการกำหนดวิธีรวมงาน ซึ่งรายวิชานี้ใช้ merge
GitHub flow ประกอบด้วย 6 ขั้น ได้แก่ สร้าง branch แก้ไขและ commit เปิด pull request แก้ไขตามความเห็น merge และลบ branch pull request คือข้อเสนอให้รวมงานซึ่งเป็นพื้นที่ของการตรวจทานและการตรวจอัตโนมัติ ส่วน protected branch บังคับให้ main รับงานผ่าน pull request ที่ได้รับการอนุมัติเท่านั้น และจะบังคับผลของ CI เพิ่มในบทที่ 5
GitFlow เหมาะกับซอฟต์แวร์ที่ออกรุ่นเป็นรอบและดูแลหลายรุ่น ส่วน GitHub flow และ Trunk-Based Development เหมาะกับการส่งมอบต่อเนื่องด้วย branch อายุสั้น การเลือก workflow ต้องโยงกับบริบท ได้แก่ ความถี่ในการส่งมอบ จำนวนรุ่นที่ดูแล และระดับของการทดสอบอัตโนมัติ code review ที่มีคุณภาพต้องระบุตำแหน่ง ปัญหา และเหตุผลหรือข้อเสนอ
สิ่งที่ส่งต่อไปยังโครงงานและ Capstone
| สิ่งที่ได้ | นำไปใช้ที่ |
|---|---|
repository ทีม devops-app และ M2 | บทที่ 4 เพิ่ม package-lock.json และ npm scripts ผ่าน pull request · ใช้ต่อทุกบทจนถึง Capstone |
branch protection ของ main | บทที่ 5 เพิ่ม required status check ของ CI |
| ประวัติ pull request และความเห็นของแต่ละคน | หลักฐานรายบุคคลของงานทีมทุกบท · หลักฐาน CLO4 ที่ต้องเห็นซ้ำ |
| ใบงานกรณีศึกษา CLO1 ชิ้นที่ 1 | ใช้เทียบพัฒนาการกับใบงาน CLO1 ในบทที่ 5, 6 และ 8 |
| Learning Log ครั้งที่ 3 | portfolio ที่ส่งในบทที่ 13 |
สรุปคำสั่งในบทนี้
| คำสั่ง | หน้าที่ |
|---|---|
git remote add origin URL, git remote -v, git remote set-url origin URL | ผูก แสดง และแก้ URL ของ remote |
git clone URL | คัดลอก repository จาก remote มาเป็น repository ใหม่ในเครื่อง |
git push -u origin ชื่อbranch, git push | ส่ง branch ขึ้น remote และบันทึก upstream |
git push origin --tags | ส่ง tag ขึ้น remote |
git ls-remote --tags origin | แสดง tag ที่มีอยู่บน remote |
git fetch, git fetch --prune | ดึงข้อมูลจาก remote และลบตัวชี้ของ branch ที่ถูกลบบน remote แล้ว |
git pull, git pull origin main | ดึงและรวม commit จาก remote เข้ากับ branch ปัจจุบัน |
git config --global pull.rebase false | กำหนดให้ git pull รวมงานด้วย merge |
git branch -a | แสดง branch ทั้งในเครื่องและบน remote |
แบบฝึกหัดท้ายบท
ตอนที่ 1 ฝึกทบทวน
ชุด FP10306343-P03 จำนวน 12 ข้อ ข้อละ 1 คะแนน รวม 12 คะแนน ครอบคลุมการรับส่งงานกับ remote ขั้นตอนของ GitHub flow และ pull request การตั้ง protected branch การเลือก Git workflow และความเห็น code review ที่มีคุณภาพ
เข้าสู่ระบบห้องเรียนด้วยบัญชีที่ลงทะเบียนในรายวิชา 10306343 แล้วตอบคำถามให้ครบ ระบบตรวจคำตอบและแสดงคำอธิบายเพื่อทบทวน เมื่อทำครบและส่งผล ระบบจะบันทึกคะแนนไว้กับบัญชีของผู้เรียน สามารถทำซ้ำเพื่อทบทวนได้ ส่วนคะแนนที่นำไปรวมในรายวิชาเป็นไปตามเกณฑ์และกำหนดส่งในสมุดคะแนน
แบบฝึกหัดเพิ่มเติมสำหรับอภิปรายและเขียนตอบ
แบบฝึกหัดแบ่งเป็นสามกลุ่ม ได้แก่ ความเข้าใจ การประยุกต์ และการวิเคราะห์ปัญหา แต่ละข้อระบุผลลัพธ์การเรียนรู้ที่ฝึก
ก. ความเข้าใจ
- ก1 (LLO 3.1) เรียงขั้นตอนของ GitHub flow ทั้ง 6 ขั้นให้ถูกลำดับ และระบุว่าขั้นใดที่ protected branch บังคับให้ต้องเกิดก่อนขั้น merge
- ก2 (เตรียมพื้น) อธิบายความต่างระหว่าง
git fetchกับgit pullและระบุว่าคำสั่งใดเปลี่ยนไฟล์ใน working tree - ก3 (LLO 3.2) ระบุ branch ถาวรของ GitFlow และหน้าที่ของ release branch กับ hotfix branch
ข. การประยุกต์
- ข1 (LLO 3.1) เขียนลำดับคำสั่งตั้งแต่สร้าง branch
docs/update-readmeจากmainล่าสุดจนถึง push branch ขึ้น remote และระบุสิ่งที่ต้องทำต่อบนหน้าเว็บจนงานเข้าmain - ข2 (LLO 3.3) ปรับความเห็น review ต่อไปนี้ให้มีตำแหน่ง ปัญหา และเหตุผล: "commit message ไม่ดี" (pull request มี commit ข้อความ
update) - ข3 (LLO 3.2) ทีม 2 คนพัฒนาเว็บไซต์ประชาสัมพันธ์ของคณะซึ่งแก้เนื้อหาเกือบทุกวัน และมีรุ่นเดียวที่เปิดใช้งาน เลือก workflow พร้อมเหตุผล 2–3 บรรทัด
ค. การวิเคราะห์ปัญหา
- ค1 (LLO 3.1) สมาชิกคนหนึ่ง push branch แล้วเปิด pull request แต่หน้า pull request แสดงไฟล์ที่เปลี่ยน 40 ไฟล์ ทั้งที่แก้ README เพียงไฟล์เดียว วิเคราะห์สาเหตุที่เป็นไปได้และวิธีตรวจสอบ
- ค2 (เตรียมพื้น) สมาชิกสั่ง
git pullแล้วได้fatal: Need to specify how to reconcile divergent branches.อธิบายความหมายของ divergent branches และวิธีแก้ที่สอดคล้องกับข้อตกลงของรายวิชา - ค3 (LLO 3.3) pull request หนึ่งได้ Approve จากสมาชิก 1 คนภายใน 30 วินาทีหลังเปิด ทั้งที่มีไฟล์
.envติดมาด้วย วิเคราะห์ว่ากระบวนการ review ของทีมมีปัญหาอะไร และเสนอข้อตกลงของทีม 2 ข้อเพื่อป้องกัน
เฉลยจะเปิดในชั้นเรียนหลังทุกคนทำเสร็จ
การศึกษาค้นคว้าเพิ่มเติม
- ศึกษาเอกสาร GitHub flow และ About protected branches แล้วสรุปกฎของ protected branch ที่ไม่ได้ใช้ในบทนี้อย่างน้อย 2 กฎ พร้อมสถานการณ์ที่ควรใช้
- ศึกษาบทความ A successful Git branching model โดยเฉพาะหมายเหตุที่เพิ่มเมื่อปี 2020 และหน้า DORA: Trunk-based development แล้วเขียนใบงานกรณีศึกษาให้เสร็จ
- ทำแบบฝึกหัดท้ายบทให้ครบ
- จัดทำงานที่ต้องส่งให้ครบทั้ง 5 ข้อ และเขียน Learning Log ครั้งที่ 3
- ทบทวน template ของ pull request ที่ทีมเพิ่มใน Lab A.3 หลังใช้งานครบหนึ่งรอบ แล้วเสนอปรับ checklist อย่างน้อย 1 ข้อผ่าน pull request พร้อมเหตุผลว่าข้อนั้นช่วยผู้ตรวจทานอย่างไร
เอกสารอ้างอิง
แหล่งข้อมูลเพิ่มเติมสำหรับตัวอย่างและกรณีอธิบาย
ตรวจเอกสารออนไลน์เมื่อ 23 ตุลาคม 2569 ตัวเลขและเหตุการณ์ที่ระบุว่าสมมติใช้เพื่ออธิบายกลไก ไม่ใช่ผลทดลองหรือสถิติขององค์กรจริง
เอกสารอ้างอิงของเนื้อหาเดิม
- DORA. (n.d.). Capabilities: Trunk-based development. https://dora.dev/capabilities/trunk-based-development/
- Driessen, V. (2010, January 5). A successful Git branching model (note added 2020, March 5). https://nvie.com/posts/a-successful-git-branching-model/
- Git project. (n.d.). git-ls-remote documentation. https://git-scm.com/docs/git-ls-remote
- GitHub. (n.d.). About protected branches. GitHub Docs. https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches
- GitHub. (n.d.). About pull requests. GitHub Docs. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests
- GitHub. (n.d.). GitHub flow. GitHub Docs. https://docs.github.com/en/get-started/using-github/github-flow
- Hammant, P. (n.d.). Trunk Based Development. https://trunkbaseddevelopment.com/