

Git Commit Convention - มาตรฐานการ Commit ที่ทำให้โค้ดอ่านง่ายขึ้น
เปลี่ยน Commit Message ธรรมดาให้เป็นระเบียบ เข้าใจง่ายและทำงานเป็นทีมได้ราบรื่นมากยิ่งขึ้น
การเขียนโค้ดโดยปกติก็ปวดหัวพออยู่แล้ว แต่สิ่งที่ทำให้ปวดหัวถัดไปเมื่อเขียนโค้ดเสร็จก็คือ การเขียน Commit Message นั่นเอง
ถ้าคุณเคยเจอ Commit Message ที่สั้นมาก ๆ และไม่สื่อความหมาย เช่น update, fix bug, asdf หรือ Commit Message ที่ยาวมาก ๆ ชนิดที่ว่า เหมือนเขียนโค้ดที่แก้ไขมาใส่ลงไป คงจะพอเห็นภาพของปัญหานี้
หากโปรเจกต์นี้มีผู้พัฒนาคนเดียวหรือเป็นทีมเล็ก ๆ ก็คงจะไม่มีปัญหาอะไร แต่หากโปรเจกต์มีขนาดใหญ่ขึ้น มีหลาย module เข้ามาเกี่ยวข้อง หรือมีนักพัฒนาหลายคน การจะไล่ประวัติการแก้ไขของโค้ด (commit history) ก็คงจะไม่ใช่เรื่องง่ายเลยทีเดียว และจุดนี้เองที่ทำให้ Git Commit Convention เข้ามามีบทบาทเป็นภาษากลางที่ทีมจะได้ใช้สื่อสารร่วมกัน
💡 Git Commit Convention คืออะไร#
Git Commit Convention คือ กติกา/มาตรฐาน ที่ช่วยกำหนดโครงสร้างการเขียน Commit Message ให้สื่อสารชัดเจน เข้าใจง่าย และเป็นระบบ เพื่อให้ทุกคนในทีมสื่อสารตรงกัน
📑 ตัวอย่าง Convention ที่นิยมใช้#
มาตรฐานของ Commit Message นั้นมีได้หลากหลายตั้งแต่มาตรฐานกลางที่ developer ยึดถือร่วมกัน ไปจนกระทั่งมาตรฐานของทีมแบบเฉพาะเจาะจง โดยทุกรูปแบบมีจุดมุ่งหมายเดียวกันคือ การจัดโครงสร้างของ Commit Message ให้เป็นระเบียบ
- Conventional Commits
เป็นรูปแบบที่ต่อยอดมาจาก Angular Commit Guidelines โดยมีลักษณะดังนี้
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]plaintextซึ่งจะมีส่วนประกอบสำคัญอยู่ 2 ส่วน คือ type และ description
โดยที่ type จะอ้างอิงมาจาก Angular Commit Guidelines เช่นกัน ซึ่งประกอบด้วย type ที่สำคัญดังนี้
- build: การแก้ไขที่เกี่ยวกับการ build dependencies ของระบบ
- ci: การแก้ไขที่เกี่ยวกับการทำ CI หรือ deployment
- docs: การอัปเดตเอกสาร
- feat: การเพิ่มฟีเจอร์ใหม่
- fix: การแก้ไขข้อผิดพลาดของระบบ
- perf: การเพิ่ม performance ของระบบ
- refactor: การ refactor code โดยไม่ได้เพิ่มฟีเจอร์หรือแก้ไขข้อผิดพลาดใด ๆ
- style: การปรับแก้ไข code style หรือ format โดยไม่ได้เพิ่มฟีเจอร์หรือแก้ไขข้อผิดพลาดใด ๆ
- test: การเพิ่มหรือแก้ไข tests ของระบบ
ตัวอย่างการ Commit Message ที่อ้างอิงมาตรฐานนี้สามารถเขียนได้ดังนี้
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config filesplaintextจะเห็นว่าเมื่ออ่าน Commit Message จะสามารถเข้าใจการเปลี่ยนแปลงได้โดยคร่าวทันที ทำให้การไล่ประวัติการแก้ไขทำได้ง่ายขึ้นมาก
สามารถอ่านรายละเอียดเพิ่มเติมได้ที่ Conventional Commits ↗
- Angular Commit Guidelines
เรียกว่าเป็นมาตรฐานต้นแบบสำหรับ Commit Convention เลยก็ว่าได้ มีลักษณะพื้นฐานทั้งหมดเหมือนกับ Conventional Commits (ซึ่งก็แน่นอนเพราะ Conventional Commits อ้างอิงมาจาก Guidelines นี้) โดยมีลักษณะดังนี้
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
│ elements|forms|http|language-service|localize|platform-browser|
│ platform-browser-dynamic|platform-server|router|service-worker|
│ upgrade|zone.js|packaging|changelog|docs-infra|migrations|
│ devtools
│
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|testplaintextซึ่งในส่วนของ Commit Scope ตัว Document ของ Angular จะมีการอธิบายเพิ่มเติมเกี่ยวกับ Scope ที่รองรับ ดังนี้
- animations
- common
- compiler
- compiler-cli
- core
- elements
- forms
- http
- language-service
- platform-browser
- platform-browser-dynamic
- platform-server
- platform-webworker
- platform-webworker-dynamic
- router
- service-worker
- upgrade
สำหรับรายละเอียดเพิ่มเติมอื่น ๆ สามารถอ่านได้ที่ Angular Commit Guidelines ↗
- Custom Team Convention
ในบางครั้งการพัฒนาภายในทีมอาจต้องการข้อมูลมากขึ้นในการตรวจสอบโค้ดหรือบริหารจัดการทรัพยากร จึงจำเป็นต้องเพิ่มข้อมูลบางอย่างเข้าไปใน Commit Message เช่น เลขของ task id เป็นต้น เพื่อให้ง่ายต่อการทำ CI/CD หรือง่ายต่อ development workflow บางอย่าง ตัวอย่าง message เหล่านี้ได้แก่
TASK-123: fix issue user loginplaintextจะเห็นว่า แม้เราจะเพิ่มข้อมูลบางส่วนไปเพื่อให้ง่ายต่อการจัดการแล้ว แต่เราก็ยังคงยึดถือ Conventional Commits บางส่วนได้ทำให้สื่อสารกับนักพัฒนากลุ่มอื่นได้เช่นกัน
🛠️ การใช้เครื่องมือช่วยตรวจสอบ Commit Message#
แม้ว่าจะมีการตกลงกันภายในทีมเป็นอย่างดีแล้ว แต่ในทางปฏิบัติจริงก็อาจมีบางครั้งที่มีการหลงลืมหรือเกิดข้อผิดพลาดในการพิมพ์ Commit Message ขึ้นได้
ซึ่งในจุดนี้เราสามารถนำเครื่องมือต่าง ๆ เข้ามาช่วยเพื่อให้ทีมสามารถทำงานได้สะดวกขึ้นดังนี้
- commitlint
เป็นเครื่องมือที่ช่วยตรวจสอบ Commit Message ของเราว่าได้พิมพ์ถูกต้องตาม Convention ที่กำหนดหรือไม่ โดยสามารถกำหนดมาตรฐานตาม Conventional Commits ได้เลย หรือจะสร้าง rules โดยเฉพาะของทีมก็ได้
ดูรายละเอียดการติดตั้ง commitlint ได้ที่ https://commitlint.js.org/ ↗
หลังจากติดตั้งแล้วให้ลองพิมพ์คำสั่ง
echo "update file" | npx commitlintbashจะเห็นว่า update file เป็น Commit Message ที่ไม่ถูกต้องตามมาตรฐาน เมื่อตรวจสอบด้วย commitlint จะได้ผลลัพธ์
⧗ input: update file
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlintplaintextแสดงว่าตัว commitlint ทำงานถูกต้องแล้ว (เพราะตรวจเจอว่า ไม่ได้ใส่ subject และ type มา)
- Git Hook ด้วย Husky
หลังจากติดตั้ง commitlint แล้ว ให้เราเชื่อมต่อตัว commitlint และ Git Hook ด้วย Husky
ซึ่งสามารถติดตั้งได้จาก https://typicode.github.io/husky/ ↗
หลังจากติดตั้งเสร็จเรียบร้อยแล้ว ให้เพิ่มคำสั่ง commit-msg เข้าไปดังนี้
npx --no-install commitlint --edit "$1"bashหลังจากนั้นให้เราลองสร้าง commit ที่มีรูปแบบที่ไม่ถูกต้องอีกครั้ง จะเห็นว่า git ของเราจะไม่อนุญาตให้ทำ commit นั้นด้วยข้อความของ commitlint ที่เราได้ติดตั้งไปก่อนหน้านี้
เมื่อทุกอย่างติดตั้งเสร็จเรียบร้อยเราสามารถแชร์ config ทั้งหมดนี้ให้ทีมใช้ร่วมกันได้ทันที
🎯 บทสรุป#
การเขียน Commit Message อาจจะดูเป็นเรื่องเล็กน้อยเมื่อเทียบกับการเขียนโค้ดโดยรวม แต่ก็เป็นอีกหนึ่งตัวช่วยให้การทำงานร่วมกันเป็นทีม เป็นไปอย่างราบรื่นมากยิ่งขึ้นไม่แพ้มาตรฐานอื่นเลย อีกทั้งยังเป็นเรื่องที่สามารถเริ่มทำได้ง่ายโดยไม่กระทบภาพรวมของทีมอีกด้วย 🥰