Git pre-commit hook ซึ่งเป็นสคริปต์ที่ทำงานอัตโนมัติก่อนที่ commit จะถูกบันทึกเสร็จสิ้น กลายเป็นจุดศูนย์กลางของการถกเถียงในวงการพัฒนาซอฟต์แวร์ ออกแบบมาเพื่อตรวจจับปัญหาต่างๆ อย่างเช่นข้อผิดพลาดในการจัดรูปแบบโค้ดหรือข้อมูลลับที่รั่วไหลตั้งแต่เนิ่นๆ hook เหล่านี้ได้รับการยกย่องจากบางฝ่ายว่าช่วยปรับปรุงคุณภาพโค้ด ในขณะที่อีกฝ่ายก็ด่าว่ามันเป็นการขัดขวางขั้นตอนการทำงาน ชุมชนนักพัฒนากำลังมีส่วนร่วมในการอภิปรายอย่างร้อนแรงเกี่ยวกับว่าประโยชน์ของ pre-commit hook นั้นมีค่ามากกว่าความสามารถในการสร้างความรำคาญและทำให้กระบวนการพัฒนาช้าลงหรือไม่
การอภิปรายครั้งใหญ่ระหว่าง Pre-Commit และ Pre-Push
ข้อผิดพลาดหลักในการสนทนาของชุมชนนั้นอยู่ที่ เวลา ที่ควรจะรันการตรวจสอบอัตโนมัติ นักพัฒนาหลายคนพบว่า pre-commit hook ขัดจังหวะขั้นตอนการทำงานตามธรรมชาติของพวกเขา โดยเฉพาะเมื่อพวกเขาทำ commit ขนาดเล็กและบ่อยครั้งเพื่อบันทึกความคืบหน้า สำหรับนักพัฒนาเหล่านี้แล้ว pre-push hook เป็นทางออกที่ตกลงกันได้มากกว่า มันอนุญาตให้พวกเขา commit อย่างอิสระระหว่างการพัฒนา และบังคับใช้การตรวจสอบคุณภาพก็ต่อเมื่อพวกเขาพร้อมที่จะแบ่งปันงานของพวกเขากับผู้อื่น สิ่งนี้ป้องกันวงจรการตอบรับของ CI อันเลื่องชื่อ ซึ่งเกิดขึ้นเมื่อนักพัฒนาพยายาม push โค้ดออกไปเพียงเพื่อให้ pipeline ระยะไกลล้มเหลวในอีกไม่กี่นาทีต่อมาด้วยปัญหาเรื่องการจัดรูปแบบง่ายๆ ที่ควรจะสามารถตรวจจับได้ในเครื่องของตัวเอง
ผมต้องการความล่าช้าเป็นศูนย์สำหรับการ commit การตรวจสอบสามารถรันกับ pull request ใน GitHub action runner ได้ ไม่มีเหตุผลที่จะบังคับให้ผมต้องรันมันบนเครื่องของผม
ผู้อื่นแย้งว่าการใช้ pre-push hook นั้นเพียงแต่ผลักปัญหาออกไปข้างหน้าเท่านั้น ทำให้ต้องมาค้นพบปัญหาที่ใหญ่กว่าทีหลังในภายต้น พวกเขาโต้แย้งว่าการได้รับคำติชมทันทีภายในเครื่องนั้นมีประสิทธิภาพมากกว่าการรอให้ CI ทำงาน หัวใจของปัญหาดูเหมือนจะเป็นการแลกเปลี่ยนระหว่างความลื่นไหลของขั้นตอนการทำงานในทันที และประสิทธิภาพในระยะยาว
อันตรายของ Hook ที่ช้าและยุ่งเกี่ยวมากเกินไป
มีความเห็นพ้องต้องกันอย่างแข็งแกร่งว่าความเร็วของ hook นั้นมีความสำคัญอย่างยิ่งต่อการยอมรับมัน หาก hook ใช้เวลารันนานกว่าสองสามวินาที มันก็จะกลายเป็นแหล่งที่มาของความขัดแย้งอย่างมีนัยสำคัญ นักพัฒนาที่ทำงานในโปรเจกต์ขนาดใหญ่รายงานว่า linter หรือชุดทดสอบที่ช้าใน pre-commit hook เป็นเหตุผลหลักที่ทำให้พวกเขาปิดการใช้งาน hook เหล่านั้นไป ภูมิปัญญาของชุมชนแนะนำว่าการตรวจสอบใดๆ ที่ใช้เวลานานกว่า 0.5 วินาที เป็นตัวเลือกที่ควรย้ายไปไว้ใน pre-push hook และการทดสอบที่ใช้เวลารันเป็นนาทีๆ ควรปล่อยไว้ให้ระบบ CI จัดการเท่านั้น
อีกจุดหนึ่งของการถกเถียงคือ hook ที่มีการแก้ไขโค้ด เช่น ตัวจัดรูปแบบอัตโนมัติ ในขณะที่บางคนชื่นชอบความสะดวกสบายนี้ แต่คนอื่นๆ ก็ต่อต้านอย่างรุนแรง พวกเขาแย้งว่าการมีสคริปต์ที่เปลี่ยนงานของคุณโดยเงียบๆ โดยไม่ได้รับความยินยอมอย่างชัดแจ้งนั้นสามารถทำให้สับสนและบางครั้งก็นำไปสู่โค้ดที่พัง ความต้องการของหลายๆ คนคือให้ hook เป็นแบบอ่านอย่างเดียว โดยที่มันสามารถทำให้ commit ล้มเหลวได้ แต่มันไม่ควรเปลี่ยนแปลงเนื้อหาของ commit นั้น
ระยะเวลาและช่วงเวลาที่แนะนำสำหรับ Hook
ขั้นตอนของ Hook | การตรวจสอบที่แนะนำ | ระยะเวลาสูงสุดที่แนะนำ |
---|---|---|
Pre-Commit | การจัดรูปแบบอัตโนมัติ, การสแกนหาข้อมูลลับแบบเร็ว | < 0.5 วินาที |
Pre-Push | การตรวจสอบโค้ดแบบเร็ว, การตรวจสอบประเภทข้อมูล, การทดสอบหน่วย | < 10 วินาที |
CI Pipeline | ชุดการทดสอบแบบเต็มรูปแบบ, การทดสอบการทำงานร่วมกัน, การตรวจสอบโค้ดแบบช้า | นาทีถึงชั่วโมง |
การ Rebase และปัญหาของ Hook
การอภิปรายที่เกี่ยวข้องกับเทคนิคมากขึ้น แต่ก็มีความหลงใหลไม่แพ้กัน คือเกี่ยวกับวิธีการที่ pre-commit hook มีปฏิสัมพันธ์กับคุณสมบัติ rebase อันทรงพลังของ Git เมื่อทำการ rebase ชุดของ commit หลายๆ commit, pre-commit hook จะทำงานสำหรับแต่ละ commit ที่กำลังถูกเล่นซ้ำ หาก hook ทำการจัดรูปแบบโค้ดอัตโนมัติ มันอาจจะแนะนำการเปลี่ยนแปลงการจัดรูปแบบในแต่ละขั้นตอน ซึ่งมีศักยภาพที่จะสร้างความขัดแย้งในการรวม (merge conflict) ขึ้นมาในจุดที่เดิมไม่มีปัญหาใดๆ แม้ว่าจะมีวิธีแก้ไขทางเทคนิค เช่น การกำหนดค่า hook ให้ตรวจจับและหยุดการทำงานตั้งแต่เนิ่นๆ ในระหว่างการ rebase แต่นี่ก็เพิ่มความซับซ้อน นักพัฒนาบางคนหลีกเลี่ยงปัญหานี้ทั้งหมดโดยใช้คำสั่งเช่น git rebase -x hook
เพื่อรันการตรวจสอบด้วยมือเฉพาะเมื่อพวกเขาต้องการ เทียบกับการบังคับให้ทำงานอัตโนมัติ
เครื่องมือ Git Hook ยอดนิยม
- Pre-Commit: เฟรมเวิร์กแบบสแตนด์อโลนสำหรับจัดการและดูแลรักษา pre-commit hooks หลายภาษา มีฟีเจอร์การจัดการ dependency สำหรับ hooks
- Husky: เครื่องมือที่ต้องใช้ Node.js และ npm ได้รับความนิยมในระบบนิเวศ JavaScript สำหรับจัดการ Git hooks
- Prek: การพัฒนาใหม่ของ Pre-Commit ที่ใช้ Rust ซึ่งยังอยู่ระหว่างการพัฒนา
การหาจุดสมดุลที่เหมาะสม
แม้จะมีข้อเสีย ชุมชนก็ยอมรับประโยชน์หนึ่งของ pre-commit hook ที่แทบจะไม่มีใครโต้แย้ง นั่นคือการป้องกันไม่ให้ข้อมูลลับถูก commit เครื่องมือเช่น Gitleaks สามารถสแกนหาคีย์ API หรือรหัสผ่านที่ถูก commit โดยไม่ตั้งใจ และการตรวจจับสิ่งนี้ภายในเครื่องถือเป็นชัยชนะด้านความปลอดภัยอย่างมาก ด้วยเหตุผลนี้เพียงอย่างเดียว ทีมงานหลายทีมพบว่าค่าใช้จ่ายในการตั้งค่า hook นั้นมีความคุ้มค่า
กุญแจสำคัญสู่การนำ hook ไปใช้อย่างประสบความสำเร็จดูเหมือนจะเป็นการคัดกรองอย่างรอบคอบ มีการสนับสนุนให้ทีมต่างๆ รวมเฉพาะการตรวจสอบที่รวดเร็วเป็นอย่างยิ่งและไม่ก่อให้เกิดการรบกวน ตัวจัดรูปแบบที่เร็วและเครื่องมือสแกนหาข้อมูลลับเป็นตัวเลือกที่ดี Linter ที่ช้าและชุดทดสอบแบบเต็มไม่ใช่เป้าหมายคือการช่วยเหลือนักพัฒนาโดยไม่กลายเป็นอุปสรรค อย่างที่ผู้แสดงความคิดเห็นคนหนึ่งกล่าวไว้อย่างกระชับ เป้าหมายคือการรักษาวงจรการทำงานให้แน่นและทำงานอยู่ตลอดเวลา
ในท้ายที่สุด การอภิปรายเผยให้เห็นว่าไม่มีทางออกใดที่เหมาะกับทุกสถานการณ์ ประสิทธิผลของ Git hook นั้นขึ้นอยู่กับขนาดของโปรเจกต์ ขั้นตอนการทำงานของทีม และประสิทธิภาพของเครื่องมือพื้นฐานเป็นอย่างมาก แม้ว่าพวกมันจะเป็นส่วนหนึ่งของกลยุทธ์การประกันคุณภาพที่มีประสิทธิภาพ แต่พวกมันต้องการการนำไปใช้อย่างรอบคอบเพื่อหลีกเลี่ยงการกลายเป็นแหล่งความ frustrate ที่นักพัฒนาเรียนรู้ที่จะหาทางอ้อมแทนที่จะทำงานร่วมกับมัน
หมายเหตุ: Rebase คือการดำเนินการของ Git สำหรับการนำชุดของ commit ไปใช้กับ base commit ใหม่ มักใช้เพื่อทำความสะอาดประวัติ
อ้างอิง: Discussion of the Benefits and Drawbacks of the Git Pre-Commit Hook