- Stacked pull requests ที่แบ่งการเปลี่ยนแปลงขนาดใหญ่ออกเป็นชั้นย่อย ๆ ที่ตรวจรีวิวได้ กำลังทยอยเปิดให้ใช้งานแบบ Public Preview ในทุก repository
- PR แต่ละรายการจะชี้เป้าไปยังชั้นที่อยู่ถัดลงมา ทำให้ทีมสามารถ รีวิว diff แบบขอบเขตแคบ ๆ ได้อย่างอิสระและขนานกัน
- เมื่อ merge PR ล่าสุด การเปลี่ยนแปลงจะถูกรวมพร้อมกับชั้นที่ยังไม่ได้ merge ด้านล่างทั้งหมดในครั้งเดียว และหาก merge เพียงบางส่วน PR ด้านบนจะถูก rebase และเปลี่ยน target โดยอัตโนมัติ
- การรีวิว PR เดิม, required checks, branch protection และเงื่อนไขการ merge ยังใช้ได้เหมือนเดิม และสามารถจัดการ stack ได้จาก GitHub.com, CLI, แอปมือถือ และ GitHub Copilot
- Public Preview จะขยายไปยัง repository ทั้งหมดในช่วงไม่กี่วัน และ การรองรับ Merge queue จะทยอยเปิดให้ใช้งานในช่วงไม่กี่สัปดาห์ถัดไป
โครงสร้าง PR สำหรับซ้อนการเปลี่ยนแปลงขนาดเล็ก
- แบ่งการเปลี่ยนแปลงขนาดใหญ่ออกเป็น PR หลายรายการที่เล็กและโฟกัสชัดเจน แล้วจัด PR แต่ละรายการเป็น ชั้นของการเปลี่ยนแปลง ที่มีลำดับ
- หลังสร้าง branch และ PR สำหรับการเปลี่ยนแปลงแรกแล้ว ให้เพิ่ม branch และ PR ต่อขึ้นไปด้านบน โดย PR แต่ละรายการจะชี้เป้าไปยังชั้นที่อยู่ถัดลงมา
- ลดความยุ่งยากจากการต้องรีวิว PR ขนาดใหญ่เพียงรายการเดียว หรือการต้อง rebase หลาย branch เองอย่างต่อเนื่อง
- ทีม Next.js ประเมินว่าแม้จะปล่อยฟีเจอร์ขนาดใหญ่ ก็ยังรักษาการเปลี่ยนแปลงแต่ละส่วนให้เล็กได้ ทำให้การรีวิว PR ง่ายขึ้น
การสร้าง stack และสภาพแวดล้อมการทำงาน
- ติดตั้งส่วนขยาย CLI ด้วยคำสั่งต่อไปนี้
gh extension install github/gh-stack
- สามารถสร้างและจัดการ stack ได้จาก GitHub.com, GitHub CLI และแอปมือถือ GitHub
- ใน coding agent อย่าง GitHub Copilot สามารถใช้ skill
gh-stack ได้
การรีวิวแยกตามแต่ละชั้น
- เมื่อเปิด PR ใน stack จะสามารถรีวิวได้เฉพาะ diff ของชั้นนั้น ไม่ใช่การเปลี่ยนแปลงทั้งหมด
- สามารถดูได้ว่าการเปลี่ยนแปลงปัจจุบันอยู่ตรงไหนของงานทั้งหมดจากแผนที่ stack ที่ด้านบนของ PR
- สมาชิกทีมสามารถรีวิวชั้นต่าง ๆ พร้อมกันแบบขนานได้ ทำให้งานถัดไปไม่ต้องถูกบล็อกจนกว่าการรีวิวจะเสร็จ
- ใช้กฎ branch protection เดิมร่วมกับการรีวิวแยกตามชั้น เพื่อควบคุมคุณภาพในแต่ละขั้นตอน
- TED ระบุว่า หลังจากนำ AI มาใช้แล้วประสิทธิภาพการพัฒนาสูงขึ้น แต่ PR ที่ใหญ่ขึ้นทำให้เกิดคอขวดในการรีวิว จึงแบ่งการเปลี่ยนแปลงออกเป็นหน่วยตรรกะขนาดเล็กตามลำดับ dependency เพื่อเพิ่มความเร็วและความแม่นยำในการรีวิว
Merge stack ทั้งหมดหรือบางส่วน
- เมื่อ merge PR ล่าสุดที่พร้อมแล้ว PR นั้นและชั้นที่ยังไม่ได้ merge ทั้งหมดด้านล่างจะถูก นำเข้าในครั้งเดียว
- สามารถเลือก merge เฉพาะบางส่วนของ stack ก่อน โดยเลือกหนึ่งชั้นหรือมากกว่าที่อยู่ด้านล่างได้เช่นกัน
- PR ด้านบนจะยังคงเปิดอยู่
- จะถูก rebase โดยอัตโนมัติให้สอดคล้องกับการเปลี่ยนแปลงที่ merge แล้ว และ target branch ก็จะถูกเปลี่ยนด้วย
- Branch protection, required checks และเงื่อนไขการ merge เดิมยังคงใช้ต่อไป เพื่อควบคุมการเปลี่ยนแปลงที่จะเข้าสู่
main
- สามารถเลือก merge เฉพาะหนึ่งชั้นหรือบางชั้นได้ ไม่ใช่แค่ทั้ง stack เท่านั้น
Public Preview และกำหนดการรองรับ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ลองใช้พรีวิวมาสักพักแล้ว และรู้สึกแปลกใจที่ขยายกลุ่มผู้ใช้ทั้งที่ยังมีปัญหาที่ยังไม่ได้แก้จำนวนมาก
ตัวอย่างเช่น การ merge ทั้ง stack พังโดยสิ้นเชิงในหลายสถานการณ์: https://github.com/github/gh-stack/discussions/212
แม้จะ merge ทีละรายการได้ แต่ถ้าใช้ squash merge ร่วมกับรีวิวที่บังคับ ทุก PR ใน stack จะต้องขออนุมัติใหม่ ทำให้เสียประโยชน์หลักที่สุดของ stacked PR ไป
gh stackช่วยลดงานทำมือได้เล็กน้อย แต่ก็ยังต้องเข้าใจgit rebaseอย่างถูกต้องอยู่ดี หาก branch ในเครื่องไม่ได้ซิงก์กับ remote คำสั่งgh stack rebaseที่ UI แนะนำก็จะล้มเหลว และเครื่องมือก็ไม่บอกสาเหตุในทางกลับกัน ชอบ stack UI เพราะเรียบง่ายแต่แสดงความสัมพันธ์ระหว่าง PR ได้เพียงพอ มันแค่ทำให้ workflow สะดวกขึ้นภายใต้สมมติฐานว่ามีเหตุผลอยู่แล้วที่ต้องซ้อน PR ไม่ใช่เครื่องมือที่ให้ฟีเจอร์ใหม่
CPRMC (Create Pull Request Merge Commit) ภายในจะตรวจตั้งแต่มี conflict หรือไม่ ไปจนถึงเนื้อหาที่อนุมัติตรงกับ commit ที่จะถูกสร้างจริงหรือไม่ เพื่อ判断ว่า PR พร้อม merge แล้วหรือยัง
หากต้องการ squash merge หลาย PR ต้องคำนวณ squash commit ต่อเนื่องกัน แล้วเชื่อมกลับเข้ากับกฎและรีวิวอีกครั้ง PR แรกค่อนข้างง่าย แต่ตั้งแต่ PR ที่สองเป็นต้นไปจะซับซ้อนขึ้น เพราะ commit บรรพบุรุษถูก squash ไปแล้วและไม่ได้อยู่ใน branch ตามรูปเดิม ส่วนกรณีที่มี parent หลายตัวจะยากกว่านั้นมาก
ตอนนี้ 99% ของการ merge stack สำเร็จ แต่การทำให้อัตรานี้สูงกว่านี้มากเป็นความสำคัญสูงสุดของทีม
mergingต่อไปโดยไม่มีคำแนะนำเพิ่มเติมนึกว่าเป็นเหตุขัดข้องบางส่วนของระบบ PR จนถึงขั้นไปดูหน้า status ของ GitHub แต่จริง ๆ เป็นบั๊กของฟีเจอร์ stacked PR เอง
ทีม GitHub Stacked PRs เปิดให้กว้างขึ้นแล้ว ตอนนี้ใคร ๆ ก็สร้าง stack ได้: https://gh.io/stacks
ต้องการ feedback โดยเฉพาะเรื่อง UI และ CLI และยังเตรียมอัปเดตอีกมากเพื่อปรับปรุงประสบการณ์การใช้ PR
นี่เป็น หนึ่งในการเปิดตัวครั้งใหญ่ที่สุดในประวัติศาสตร์ GitHub ครอบคลุมแทบทุกบริการ ตั้งแต่ Actions และ protection rules ไปจนถึง CLI และแอปมือถือ จึงสามารถตอบคำถามเกี่ยวกับการตัดสินใจด้านการออกแบบและกลไกภายในได้ด้วย
ตอนนี้มี UI local ของตัวเองที่ดู dependency ของ stacked PR เป็น tree และจัดการสถานะรีวิว/CI ของแต่ละ PR อยู่แล้ว จึงอยากให้ GitHub web UI มี tree และการแสดงสถานะ ด้วย
ใน web UI ดูเหมือนยังไม่รองรับการ merge เฉพาะ PR ล่างสุดของ stack แต่สามารถแชร์ workflow และโค้ดที่มีอยู่ได้ จึงหวังว่าจะเข้าไปอยู่ในเครื่องมือพื้นฐานของ GitHub ด้วย
สำหรับให้มีประโยชน์ใน repository สาธารณะ มันดูเป็นฟีเจอร์สำคัญ เลยแปลกใจที่ไม่ได้มาก่อน public preview
แทนที่จะมี UI ที่เหมาะสมสำหรับรีวิว/นำไปใช้/แก้ไขเป็นราย commit อยากรู้ว่ามี insight พิเศษอะไรหรือไม่ที่ทำให้เลือกวิธีนี้ ซึ่งแทบจะเป็น ‘ชุดของชุดแพตช์’ โดยละเลย workflow แบบ patch series ของ mailing list ที่เป็นต้นกำเนิดของแนวทางนี้
เป็นหนึ่งในการเปลี่ยนแปลงครั้งใหญ่ที่สุดที่นำมาใช้กับ GitHub ในรอบหลายปี
เมื่อ stacked workflow ถูกนำเข้าสู่หนึ่งในแพลตฟอร์มโฮสต์โค้ดขนาดใหญ่ที่สุดของโลก นักพัฒนาจำนวนมากอาจได้สัมผัสวิธีทำงานที่ไม่เคยรู้ด้วยซ้ำว่ามีอยู่
หากสมมติฐานที่ว่า stack ทำให้ซอฟต์แวร์ดีขึ้นเป็นจริง ก็มีโอกาสสูงที่จะช่วยนักพัฒนาจำนวนมากได้จริง
สงสัยว่า stacked PR แบบนี้มีข้อดีอะไรเมื่อเทียบกับการรีวิว commit ที่จัดระเบียบไว้อย่างดีทีละ commit
ปัญหาที่ใหญ่กว่าคือ PR ขนาดใหญ่ที่สร้างโดย AI ต้องมีวิธีรีวิวแยกต่างหาก แค่ลำดับการแสดง diff เช่น แสดงการเปลี่ยน function definition, call site, test ตามลำดับ ก็ทำให้อ่านง่ายขึ้นอย่างมากแล้ว
อาจต้องมี literate diff หรือ literate PR ที่ผสาน diff กับคำอธิบาย เหมือนที่ literate programming ถักทอ code กับ prose เข้าด้วยกัน แต่ยังหาเครื่องมือคล้ายกันไม่เจอ
หน่วยรีวิวอย่าง PR หรือ diff จะถูกคงไว้เป็นการเปลี่ยนแปลงที่จำกัดหนึ่งรายการ ทำให้การอภิปรายโฟกัสอยู่กับการเปลี่ยนแปลงนั้น และแม้ฟีเจอร์จะใหญ่ขึ้น ตัว PR เองก็ไม่บวม
อีกทั้งยังมอบหมายแต่ละส่วนของ stack ให้คนละกลุ่มได้ เช่น แยก reviewer เป็นทีมภายนอก เพื่อนร่วมทีม หรือทีมที่ใช้การเปลี่ยนแปลงนั้น ทำให้ไม่คลุมเครือว่าแต่ละคนอนุมัติอะไร
ถ้า GitHub review นำ change ID มาใช้เพื่อคง comment ไว้ได้แม้หลัง rebase ก็จะยิ่งดี
การที่ต้อง rebase และแก้ PR ถัด ๆ ไปก็เหมือนกับการแก้ commit ต่อท้ายใน PR ใหญ่ก้อนเดียว แต่แทนที่จะสุ่มแปะ commit แก้ชั่วคราวลงไปทั้งชุดการเปลี่ยนแปลง จะ รักษา commit ของการเปลี่ยนแปลงฐานให้อยู่รวมกันได้ง่ายขึ้น
การอภิปรายเกี่ยวกับการเปลี่ยนแปลงฐานก็จะถูกรวมไว้ด้วยกัน และเมื่อแสดง stack ทั้งหมดล่วงหน้า reviewer จะเห็นทิศทางสุดท้าย ขณะที่งานยังเดินต่อแบบ asynchronous ได้
มักใช้ commit เหมือนจุดเซฟเกม ทิ้งข้อความอย่าง
fix bug,do workแล้วไม่จัดระเบียบด้วยgit rebase -iดังนั้นถ้าไม่เปิดใช้ squash merge แบบบังคับ log ก็จะเต็มไปด้วย commit ขยะสำหรับนักพัฒนาแบบนี้ PR ก็คือ commit และ stacked PR ทำให้ในที่สุดสามารถใช้โครงสร้างที่คล้ายกับหลาย commit ที่ประกอบเป็นการเปลี่ยนแปลงหนึ่งรายการได้
diff ที่ merge แล้วสามารถ rebase ไปบน HEAD ปัจจุบันได้ และในทีมที่รองรับแนวทางนี้ โดยปกติจะไม่จัดการ branch โดยตรง แต่จะ ทำงานจาก trunk และ rebase ทุกครั้งที่มีการเปลี่ยนแปลงเข้ามา
ถ้า 4 ส่วนแรกของฟีเจอร์พร้อมแล้ว และส่วนที่ 5 มีปัญหา ก็ไม่จำเป็นต้องบล็อกทั้งหมด
สงสัยว่ากรณีที่ PR ที่มี dependency ต่อกันไม่ได้เป็นประวัติแบบเส้นตรง แต่เป็น โครงสร้างแบบต้นไม้ จะรองรับเมื่อไร
ตอนใช้การเปลี่ยนแปลงแบบ stacked ที่ Google กรณีแบบนี้พบได้บ่อย และตอนนี้ที่มีเอเจนต์เขียนโค้ดแบบขนานมากขึ้น ก็น่าจะเกิดบ่อยยิ่งขึ้น
สงสัยว่าเหตุผลที่ปุ่มสลับเมนูเป็นอีโมจิกองแพนเค้ก (U+1F95E) เพราะฟีเจอร์ stack หรือไม่
การเล่นมุกแบบนี้เองก็โอเค แต่เป็น UI ที่ทำให้เกิดความสงสัยอย่างแรงว่ากำลังดูอะไรอยู่
ตั้งใจจะแสดงเพียงไม่กี่ชั่วโมงแล้วเปลี่ยนกลับเป็นไอคอนปกติ
ใช้ CLI
gh stackมาตั้งแต่ได้ยินข่าวครั้งแรก และตัวเครื่องมือเองดีมาก แต่เว็บ UI ที่ได้เข้าถึงหลังได้รับอนุมัติให้ใช้พรีวิวนั้นต่ำกว่าที่คาดไว้มากก่อนอนุมัติ CLI ก็ช่วยให้ทำ automation เพื่อแบ่งงานออกเป็น PR แบบ atomic หลายรายการได้ง่ายอยู่แล้ว แต่เมื่อ push ขึ้นไปจะแสดงเป็น PR อิสระที่ไม่เชื่อมโยงกัน
หลังอนุมัติก็แทบเหมือนเดิมทั้งหมด มีเพียง dropdown นำทางเล็ก ๆ ด้านบนที่แสดง PR อื่นใน stack เดียวกัน จึง แทบไม่มีการเปลี่ยนแปลง UI ที่มีนัยสำคัญ
ใน dropdown สามารถทำฟังก์ชันของ CLI ได้บางส่วน แต่คล้ายความสะดวกเสริมอย่างฟีเจอร์แก้ไฟล์บนเว็บมากกว่า และใน workflow การพัฒนาจริง CLI หรือปลั๊กอิน IDE น่าจะเป็นศูนย์กลาง
จึงสงสัยว่าทำไม UI แบบเลือกใช้ได้ระดับนี้ถึงทำให้เลื่อนการเปิดสาธารณะทั่วไปมานาน ทั้งที่ stack CLI อยู่ในสถานะเปิดให้ใช้ทั่วไปมาตั้งแต่ตอนประกาศแล้ว
จะรวมถึงหน้าจอที่รับรู้ stack อยู่เสมอและแสดง stack อย่างต่อเนื่อง เพื่อให้ข้ามไปมาระหว่างแต่ละชั้นได้โดยไม่ต้องคลิกเยอะ
jujutsu ดีตรงที่เมื่ออัปเดต branch แล้ว branch อื่นที่แตกออกจาก branch นั้นจะถูก rebase ให้อัตโนมัติด้วย
เวลาต้องแบ่งงานเพื่อให้รีวิวง่าย มักสลับไปใช้
jjและแม้จะใช้ร่วมกับสำเนาที่สร้างด้วย Git ใน working directory เดียวกัน ก็ทำงานได้ดีjj absorbก็ยอดเยี่ยมเช่นกันเพราะย้ายการเปลี่ยนแปลงไปยัง change ที่เกี่ยวข้องใกล้ที่สุด ทำให้จัดการการแก้ไขที่กระทบหลาย PR ได้ง่าย
หลังจากใช้ Graphite แล้ว กลับไปใช้ GitHub ที่ไม่มี stack ได้ยากมาก
หวังว่าการรองรับของ GitHub จะทำให้ workflow แบบ stacked PR กลายเป็นเรื่องแพร่หลาย และมีทางเลือกที่ง่ายแทน PR ขนาดมหึมา
git-spiceเป็นโอเพนซอร์สที่ใช้ง่ายและทรงพลัง ส่วน Graphite รู้สึกซับซ้อนเกินไปเมื่อเทียบกับฟีเจอร์ที่มี
เข้าใจว่าการซ้อน PR มีประโยชน์ในสองกรณี
อย่างแรกคือเมื่อเกี่ยวข้องกับหลาย repository ที่สัมพันธ์กันจนรวมเป็น PR เดียวไม่ได้ และอย่างที่สองคือเมื่อซ้อน PR ถัดไปไว้บน branch เดียวกันระหว่างรอรีวิว PR แรก เพื่อทำให้งานเป็น pipeline
แต่ฟีเจอร์นี้ดูเหมือนไม่ตอบโจทย์ทั้งสองอย่าง และดูเป็นอีกรูปแบบหนึ่งของการซ้อน commit ไว้ใน PR เดียว
โดยทั่วไปเราจะสร้าง commit ที่ atomic และมีความหมาย แล้วใช้ rebase จัดลำดับให้ reviewer เข้าใจง่าย และ reviewer ก็สามารถดูทีละ commit ได้หากต้องการ
สงสัยว่า ข้อได้เปรียบเฉพาะตัว ที่วิธีนี้กำลังมองข้ามคืออะไร