วิธีทำให้เวิร์กโฟลว์การพัฒนาทีมของคุณง่ายขึ้นด้วย Git Hooks
เผยแพร่แล้ว: 2022-03-10ข้อกำหนดหลักประการหนึ่งในการทำงานให้กับทีมหรือโครงการโอเพนซอร์สคือการใช้ระบบควบคุมเวอร์ชัน (VCS) Git คือระบบควบคุมเวอร์ชันโอเพ่นซอร์สแบบแจกจ่ายฟรีสำหรับการติดตามการเปลี่ยนแปลงซอร์สโค้ดระหว่างการพัฒนาซอฟต์แวร์ มันถูกสร้างขึ้นโดย Linus Torvalds ในปี 2548 เพื่อพัฒนาเคอร์เนล Linux ง่ายต่อการเรียนรู้และมีขนาดเล็กพร้อมประสิทธิภาพที่รวดเร็วดุจสายฟ้า
มีโอกาสสูงที่คุณจะใช้ Git อยู่แล้ว (เนื่องจากเป็นเครื่องมือ VCS ที่ได้รับความนิยมและนำมาใช้อย่างดีที่สุดในชุมชนการพัฒนา) และส่วนใหญ่แล้วคุณอาจมีความรู้เกี่ยวกับการจัดเตรียมและการคอมมิตโค้ดของคุณโดยการกดและดึง จากที่เก็บระยะไกล บทความนี้จะไม่กล่าวถึงพื้นฐานของเวิร์กโฟลว์ git แต่ส่วนใหญ่จะ เน้นที่ git hooks และวิธีใช้งาน เพื่อให้เกิดการทำงานร่วมกันในทีมของคุณได้ดียิ่งขึ้น เมื่อทีมเติบโตขึ้น การรักษาผู้ร่วมให้ข้อมูลให้อยู่ในแนวเดียวกันและรักษากฎเกณฑ์ต่างๆ เกี่ยวกับโค้ดจึงมีความสำคัญมากขึ้น
Git Hooks คืออะไร?
Git hooks เป็นสคริปต์ที่ทริกเกอร์เมื่อมีการดำเนินการหรือเหตุการณ์เฉพาะในที่เก็บ git การดำเนินการเหล่านี้เกี่ยวกับส่วนต่างๆ ของเวิร์กโฟลว์การควบคุมเวอร์ชัน เช่น การคอมมิตและการพุช Hooks มีประโยชน์อย่างยิ่งโดยทำให้งานอัตโนมัติบนเวิร์กโฟลว์ git ของคุณทำงาน ตัวอย่างเช่น พวกเขาสามารถช่วยเราตรวจสอบไวยากรณ์ของ codebase ของเราตามกฎเฉพาะบางอย่าง หรือทำการทดสอบบางอย่างก่อนที่จะทำการเปลี่ยนแปลงของเรา
วิธีการรับพวกเขาตั้ง?
Git hooks เป็นคุณสมบัติในตัว หมายความว่าเราสามารถเข้าถึงพวกมันและเริ่มใช้งานได้ตราบใดที่มีการเริ่มต้นที่เก็บ git มาดูรายละเอียดเพิ่มเติมว่าการพยายามตั้งค่านั้นหมายความว่าอย่างไร
ใช้เทอร์มินัลที่คุณชื่นชอบ สร้างที่เก็บ git ใหม่
mkdir my-new-repository && cd my-new-repository git init ls -la
คุณจะสังเกตเห็นว่าเพิ่งสร้างไดเร็กทอรีที่ซ่อนอยู่ใหม่ โฟลเดอร์ .git
นี้ใช้จาก git เพื่อจัดเก็บข้อมูลที่เกี่ยวข้องกับที่เก็บ เช่น แฮชควบคุมเวอร์ชัน ข้อมูลเกี่ยวกับการคอมมิต ที่อยู่ที่เก็บระยะไกล และอื่นๆ นี่เป็นโฟลเดอร์ที่ hooks ใช้งานได้จริงสำหรับ git .git/hooks
คุณสามารถค้นหาสคริปต์ตัวอย่างที่เติมไว้ล่วงหน้าบางส่วนที่สร้างขึ้นโดยอัตโนมัติในระหว่างการเริ่มต้น อันที่จริงแล้วสคริปต์เหล่านี้จะถูกทริกเกอร์หลังจากดำเนินการบางอย่าง
ls .git/hooks
ตัวอย่างบางส่วนที่คุณสามารถหาได้คือ:
-
pre-commit.sample
: เรียกใช้ก่อนทำการคอมมิต -
commit-msg.sample
: แก้ไขไฟล์ข้อความในตำแหน่ง -
post-receive.sample
: เรียกใช้หลังจากอัปเดตที่เก็บระยะไกลแล้ว
ภายใต้ประทุน
ตอนนี้เรารู้แล้วว่าสามารถหา hooks ได้จากที่ใด ให้ย้อนกลับไปเพื่อทำความเข้าใจว่ามันทำงานอย่างไร
Git hooks เป็นแบบอิงตามเหตุการณ์ ตราบใดที่เรารันคำสั่ง git ในขั้นตอนการพัฒนา git จะตรวจสอบโฟลเดอร์ hooks เพื่อดูว่ามีสคริปต์ที่เกี่ยวข้องให้รันหรือไม่ สคริปต์เหล่านี้บางส่วนจะทำงานก่อนหรือหลังการดำเนินการขั้นตอนการพัฒนาเหล่านี้
ตัวอย่างที่ดีสำหรับเราในการดำเนินการและเข้าใจโฟลว์ที่ hook ถูกทริกเกอร์อย่างเจาะจงมากขึ้นคือเวิร์กโฟลว์ที่ยอมรับซึ่งเป็นกรณีการใช้งานที่ค่อนข้างคุ้นเคย
เมื่อใดก็ตามที่เราทำการเปลี่ยนแปลงใดๆ กับ codebase ตะขอที่เกี่ยวข้องเหล่านี้บางส่วนจะถูกทริกเกอร์ในลำดับต่อไปนี้:
-
pre-commit
: ตรวจสอบสแนปชอตที่กำลังจะคอมมิต และตรวจสอบสิ่งที่จะคอมมิต -
prepare-commit-msg
: ให้คุณแก้ไขข้อความเริ่มต้นก่อนที่ผู้เขียนคอมมิตจะเห็น -
commit-msg
: ตั้งค่าข้อความยืนยันไปยังเทมเพลต -
post-commit
: เรียกใช้การดำเนินการหลังจากที่คอมมิตเสร็จสิ้น และส่งการแจ้งเตือนเป็นต้น
ในที่เก็บข้อมูลด้านบน ตอนนี้ ให้ลองเพิ่มสคริปต์ก่อนและหลังการคอมมิตแบบกำหนดเองเพื่อให้เห็นภาพว่า git hooks ทำงานจริงอย่างไร
nano .git/hooks/pre-commit
เพิ่มข้อมูลโค้ดต่อไปนี้:
#!/bin/sh echo Changes are about to be committed
ตรวจสอบให้แน่ใจว่าสคริปต์ของเราสามารถดำเนินการได้:
chmod +x .git/hooks/pre-commit
ทำซ้ำขั้นตอนข้างต้นสำหรับสคริปต์ post-commit
:
nano .git/hooks/post-commit
#!/bin/sh echo Changes have been committed
chmod +x .git/hooks/post-commit
ตอนนี้ เราสามารถเพิ่มไฟล์ใหม่ nano index.html
ด้วยข้อมูลโค้ด HTML ขนาดเล็กเพื่อการสาธิตเท่านั้น (ไม่จำเป็นต้องให้โปรแกรมตรวจสอบ HTML ทราบเกี่ยวกับเรื่องนี้)
<h1>Hello world from our new repository!</h1>
เราจะเพิ่มการเปลี่ยนแปลงใน codebase ของเราผ่านการ staging แล้วทำสิ่งนี้:
git add . git commit
หลังจากประมวลผลเสร็จเรียบร้อยแล้ว เราจะเห็นผลลัพธ์ต่อไปนี้ของสคริปต์ที่เพิ่มไว้ด้านบนสองตัวต่อไปนี้:
Changes are about to be committed Changes have been committed
ตามที่คาดไว้ git ทริกเกอร์ hooks ในโฟลว์การส่ง สคริปต์ pre-commit
และ post-commit
ที่เพิ่มเข้ามากำลังทำงานและจะดำเนินการในลำดับที่ถูกต้อง (ตามลำดับที่เรากล่าวถึงก่อนหน้านี้)
นี่เป็นการสาธิตง่ายๆ เพื่อให้เข้าใจว่าสคริปต์เวิร์กโฟลว์การคอมมิตทำงานอย่างไรและดำเนินการอย่างไร สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเวิร์กโฟลว์นี้ คุณสามารถอ่านเพิ่มเติมในเอกสารประกอบ
ในตัวอย่างข้างต้น เราเลือกที่จะเขียนสคริปต์ทั้งสองนี้ในรูปแบบ bash แต่ความจริงก็คือ git รองรับ hooks ที่สามารถเขียนในภาษาสคริปต์ใดก็ได้ที่เราต้องการ Ruby, Python หรือ JavaScript เป็นทางเลือกที่ดี ตราบใดที่เราตั้งค่า shebang ที่ถูกต้องที่บรรทัดแรกของสคริปต์สั่งการของเรา
ตัวอย่างเช่น เราสามารถเขียน hook pre-commit
ใหม่เป็นสคริปต์ Node.js ดังนี้:
#!/usr/bin/env node console.log("Changes are about to be commited")
Hooks ในพื้นที่และระยะไกล
ตะขอถูกแยกระหว่างโลคัลและรีโมต (หรือไคลเอนต์และเซิร์ฟเวอร์) ในขณะที่ hooks โลคัลรันก่อนหรือหลังการดำเนินการเฉพาะบนที่เก็บโลคัล hooks ระยะไกลจะทำงานก่อนหรือหลังพุชไปยังเซิร์ฟเวอร์ ไม่สามารถใช้นโยบายท้องถิ่นในการบังคับใช้นโยบายได้เนื่องจากลักษณะของนโยบายช่วยให้นักพัฒนาแก้ไขได้อย่างง่ายดาย ส่วนใหญ่จะใช้สำหรับยึดติดกับหลักเกณฑ์เฉพาะบางอย่างที่เราต้องการนำไปใช้ภายในทีม ในกรณีที่เราต้องการเข้มงวดมากขึ้นและบังคับใช้นโยบายบางอย่างสำหรับที่เก็บของเรา เราอยู่ใน Remote hooks
ตะขอท้องถิ่น
-
pre-commit
-
prepare-commit-msg
-
commit-msg
-
post-commit
-
applypatch-msg
-
pre-applypatch
-
post-applypatch
-
pre-rebase
-
post-rewrite
-
post-checkout
-
post-merge
-
pre-push
ตะขอระยะไกล
-
pre-receive
-
update
-
post-receive
ตะขอแบ่งปัน
Git hooks ทั้งหมดเกี่ยวกับการแบ่งปันภายในทีม นี่คือเหตุผลหลักที่สิ่งเหล่านี้มีอยู่: ส่งเสริมการทำงานร่วมกันในทีมที่ดีขึ้น ทำให้กระบวนการที่เป็นอันตรายเป็นไปโดยอัตโนมัติ และปล่อยให้เรามุ่งความสนใจไปที่ส่วนสำคัญของ Codebase เท่านั้น
ตามที่ระบุไว้ก่อนหน้านี้ .git/hooks
เป็นโฟลเดอร์ที่โฮสต์ hooks ที่กำหนดเองของเรา แต่สิ่งนี้ไม่มีประโยชน์จริง ๆ เมื่อเราต้องการแชร์สคริปต์เหล่านี้ภายในทีม เนื่องจาก git ไม่ได้ติดตามโฟลเดอร์นี้
วิธีที่ดีในการแก้ปัญหานี้คือการเพิ่ม hooks ที่กำหนดเองทั้งหมดของเราลงในโฟลเดอร์แยกต่างหากภายในที่เก็บของเรา ตัวอย่างเช่น เราสามารถเพิ่มโฟลเดอร์ .githooks
และบันทึกสคริปต์สั่งการได้ที่นั่น จากนั้นในการเริ่มต้นโครงการ เราสามารถคัดลอกหรือเชื่อมโยงสคริปต์เหล่านี้อย่างชัดเจนไปยังโฟลเดอร์เดิมเพื่อเก็บ hooks .git/hooks
ของเราไว้
find .git/hooks -type l -exec rm {} \\; find .githooks -type f -exec ln -sf ../../{} .git/hooks/ \\;
หรือหากคุณใช้ git เวอร์ชันล่าสุด (พูดถึง 2.9
ขึ้นไป) เราสามารถกำหนดค่าพาธ git hooks ไปยังโฟลเดอร์ที่กำหนดเองได้โดยตรง:
git config core.hooksPath .githooks
Git Hooks ทำได้ง่าย (กรณีการใช้งาน JavaScript Codebase)
มีเครื่องมือที่ช่วยให้เรารวม git hooks เข้ากับความต้องการของ codebase ของเราได้มากขึ้น โดยเฉพาะสำหรับฐานรหัส JavaScript มี Husky ที่เราสามารถปรับแต่งการกระทำบนเหตุการณ์ git ผ่านการกำหนดค่าได้อย่างง่ายดาย
ตัวอย่างเช่น เราสามารถ lint โค้ดของเราหรือรันการทดสอบบางอย่างในเหตุการณ์ pre-commit
และดำเนินการคอมมิตได้โดยพิจารณาจากว่าการ linting การทดสอบหรือทั้งสองอย่างประสบความสำเร็จหรือไม่
สามารถทำได้โดยขยายการกำหนดค่า package.json
ง่ายๆ ดังนี้:
{ "scripts": { "test": "echo Running tests" }, "devDependencies": { "eslint": "5.16.0", }, "husky": { "hooks": { "pre-commit": "eslint . && npm test", } } }
บทสรุป
ในบทความนี้ เราพบว่าการดำเนินการต่างๆ ที่เกิดขึ้นกับที่เก็บ git สามารถเรียกสคริปต์ที่กำหนดเองให้ทำงาน สคริปต์เหล่านั้นสามารถอยู่ภายใต้การควบคุมของนักพัฒนาในพื้นที่หรือจัดการจากส่วนกลางมากขึ้นสำหรับทีมหรือโครงการบนรีโมต นอกจากนี้เรายังได้เรียนรู้ว่าสคริปต์มักเขียนในเชลล์สคริปต์ เช่น bash แต่จริงๆ แล้วสามารถใช้ภาษาสคริปต์ได้เกือบทุกภาษา แม้แต่ JavaScript
Git hook สามารถเป็นส่วนที่ทรงพลังมากของเวิร์กโฟลว์ที่ออกแบบมาอย่างดี และผมขอแนะนำให้คุณลองดูและดูว่าคุณสามารถทำอะไรกับโปรเจ็กต์ของคุณเองได้บ้าง