แหล่งรวบรวมความรู้พื้นฐานและ Best Practices
Table of Contents
- 📝 Conventional Commits
- 🌈 Why Use Conventional Commits
- 🧰 type (require)
- 🖍️ description (require)
- 📄 body (optional)
- 🩴 footer (optional)
- 💥BREAKING CHANGE
- 🎭 Examples
- 🍭 Bonus
- ❓ FAQ
- 🧷 Ref;
A specification for adding human and machine readable meaning to commit messages
ข้อตกลงอย่างง่ายในการเขียน Commit message อ้างอิงจาก conventional commits v1.0.0
- ช่วยให้สามารถเขียน automated tools on top ได้ง่ายขึ้น
- ช่วยในการทำ CHANGELOG แบบอัตโนมัติ
- ช่วยในการจับความหมายของ version อัตโนมัติ ตามประเภทของ commit
- การมี Trigger เพื่อสั่งให้ Build / Publish ฟีเจอร์ต่าง ๆ ได้ด้วยตัวระบบเอง
- etc.
- ช่วยในการสื่อสารบ่งบอกสิ่งที่เปลี่ยนแปลงไป ให้กับเพื่อนร่วมทีม หรือ คนอื่น ๆ
- เป็นเหมือนกฎง่าย ๆ ทำให้มี commit history ที่ชัดเจน
- ช่วยให้ผู้คนมีส่วนร่วมใน Project ของคุณได้ง่ายขึ้น โดยเฉพาะอย่างยิ่งกับ Project ที่มี commit history จำนวนมาก
เนื่องจาก conventional commits v1.0.0 สนับสนุนเรื่องความยืดหยุ่น เพื่อให้สามารถนำข้อตกลงหรือ structure ไปปรับใช้ได้ตามสะดวก ซึ่งในแต่ละที่เราก็อาจจะพบ structure ที่แตกต่างกันไปบ้าง ตามแต่ข้อตกลงกันในแต่ละที่
structure ที่เราจะใช้กันที่นี่ คือแบบนี้ ซึ่งจะแตกต่างจาก conventional commits v1.0.0 นิดหน่อย
<type-with-emoji>: [optional JIRA-ID]: <description>
[optional body]
[optional footer(s)]
- 🌟 feat: เมื่อเพิ่มคุณสมบัติใหม่ (feature)
- 🐛 fix: เมื่อแก้ไขข้อผิดพลาด (bug fix)
- 🔧 chore: เมื่อมีการเปลี่ยนแปลงค่า Ignore หรือค่า Settings ที่ไม่กระทบกับ Code โดยตรง (เช่นที่: .gitignore หรือ .prettierrc)
- ♻️ refactor: การทำความสะอาดโค้ดให้อ่านง่าย เข้าใจมากยิ่งขึ้น (เช่น การเปลี่ยนชื่อตัวแปร/ ชื่อฟังก์ชัน) ปรับปรุงโครงสร้างภายใน โดยที่ไม่เกี่ยวข้องกับการเพิ่ม feature ใหม่ หรือแก้ bug
- 📝 docs: เมื่อเปลี่ยนแปลงที่เกี่ยวข้องกับเอกสาร เช่น README หรือ markdown file อื่น ๆ
- 💄 style: เมื่อเกี่ยวข้องกับ styling เช่น code formatting, การลืมใส่ semi-colins
- ✅ test: เมื่อเกี่ยวข้องกับการเขียน Testing เพิ่ม หรือ Refactoring tests โดยที่ไม่เกี่ยวข้องกับ Production code
- ⚡️ perf: เมื่อทำการเพิ่มประสิทธิภาพ (performance)
- 💚 ci: ปรับปรุง เปลี่ยนแปลง CI Config ของไฟล์ หรือ สคริปต์ เช่น Travis, Circle, BrowserStack
- 👷 build: เมื่อเกี่ยวข้องกับการ build ระบบ เช่น ปรับปรุง build config หรือ dependency ภายนอก เช่น npm, gulp, broccoli, etc.
- ⏪️ revert: revert commit
ในกรณีต้องการนิยาม type ใหม่ขึ้นมาเอง ก็สามารถทำได้ เพราะ Conventional Commits สนับสนุนเรื่องความยืดหยุ่น เพื่อเป็นประโยชน์ต่อการอ่านและแบ่งประเภท commit รูปแบบใหม่ ๆ หรือ สร้าง type ใหม่มาเพื่อช่วยในการทำ automate tool ก็ย่อมทำได้เช่นกัน
ควรนิยามและตั้งวิธีใช้ที่ชัดเจนเพื่อให้คนในทีมเข้าใจตรงกันด้วยนะ
- type ใช้ UPPERCASE หรือ lowercase ก็ได้ ตามแต่ละที่ตกลงกัน แต่ควรใช้ให้เหมือน ๆ กันหมด
- ทางนี้จะใช้ lowercase (🌟 feat: ...) เนื่องจากพิมพ์ง่ายสุด ๆ และเห็นจากที่อื่น ๆ นิยมใช้ lowercase มากสุด
- เป็นเหมือน สรุปสั้น ๆ เกี่ยวกับการเปลี่ยนแปลงที่เกิดขึ้น
- Description จะต้องอยู่ต่อจากเครื่องหมาย
:
ที่อยู่หลังจาก type และเว้นวรรค 1 ครั้ง - Description นั้นมักจะเขียนในรูปแบบของ Imperative Mood หรือ การเขียนในรูปแบบประโยคคำสั่ง / ร้องขอ เช่น "fix bug …" หรือ "add function …"
- เป็นส่วนที่ควรระบุ และควรเขียนเป็นภาษาอังกฤษ โดยใช้ Present tense (e.g. ใช้อย่าใช้ "added" หรือ "adds" ให้ใช้ "add" แทน)
- ไม่จำเป็นต้องใช้
.
(dot) เมื่อจบประโยค - ไม่จำเป็นต้องใช้ตัวอักษรพิมพ์ใหญ่สำหรับขึ้นต้นประโยค
เพิ่มความเข้าใจได้อย่างรวดเร็ว ใน description ด้วย emoji ที่สื่อถึงความหมายจาก https://gitmoji.dev/
ตัวอย่างที่คิดว่า น่าจะใช้บ่อย ๆ
🌟 feat: ETLP-123: 👔 add read_profile business logic
👷 build: ETLP-123: 🧱 infrastructure related changes
✅ test: ETLP-123: 🧪 add a failing test
🔧 chore: 🙈 add or update a .gitignore file
🌟 feat: ETLP-123: 🗃️ perform database related changes
♻️ refactor: ETLP-123:🚚 move or rename resources (e.g.: files, paths, routes)
🐛 fix: HEIM-1234:🚑️ critical hotfix
ลงรายละเอียดของการเปลี่ยนแปลง เช่น เราแก้ไข Bug ตัวนี้ได้ยังไง, ปัญหาที่เราพบ, ขั้นตอนการทำงานของอะไรบางอย่าง
- commit ใส่ได้ตามอิสระ และอาจจะมีหลายย่อหน้าก็ได้
- body จะต้องเริ่มด้วยการเว้นบรรทัดว่างหนึ่งบรรทัดหลังจาก description ในบรรทัดแรก
จะกล่าวถึงผลที่เกิดจากการเปลี่ยนแปลง เช่น การประกาศการเปลี่ยนแปลงที่จะเกิดขึ้น (breaking) การเชื่อมโยง issues ที่ปิด การกล่าวถึง contributors และอื่น ๆ
- จะต้องเริ่มด้วยการเว้นบรรทัดว่างหนึ่งบรรทัดหลังจาก boddy หรือ description
- สามารถมีมากกว่า 1 footer ได้
- footer ประกอบด้วย
<word-token>: <value>
(e.g.Reviewed-by: username
) หรือ<word-token> #<value>
(e.g.Closes #123
)ที่นี่เราไม่ได้ใช้ issue ของ git เลย (หน้าตา git issue e.g.
#123
) จะใช้จาก jira issue-id (e.g.ETLP-12
) ซะมากกว่า จึงจะไม่ได้เห็นการใช้<word-token> #<value>
ของที่นี่ - word-token ของ footer จะต้องใช้
-
แทนการเว้นววรรค เช่นAcked-by
เพื่อให้ง่ายต่อการแยกแยะข้อความว่าเป็น body หรือ footer- ยกเว้น
BREAKING CHANGE
ที่สามารถนำมาใช้เป็น word-token ได้เลย
- ยกเว้น
Reviewed-by: Z
Refs: #123
Closes: ETLP-222, ETLP-222, ETLP-222
BREAKING CHANGE: drop code unsupport for python 3
commit ที่มี footer BREAKING CHANGE:
หรือ type ที่มี !
ต่อท้าย หมายถึง มีการเพิ่มการเปลี่ยนแปลงที่กระทบกับระบบเดิมอย่างมาก (การเปลี่ยนแปลงระดับ MAJOR
)
- footer ของ
BREAKING CHANGE
ต้องพิมพ์ในลักษณะBREAKING CHANGE: <value>
- BREAKING CHANGE ต้องพิมพ์ใหญ่ทั้งหมด (UPPERCASE)
- สามารถระบุได้กับทุก type
- ทุก Commit ที่มี Breaking change จะทริกเกอร์เมื่อมีการทำ MAJOR release และจะแสดงบน Changelogs ตามแต่ละ Commit type
🌟 feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
🌟 feat!: send an email to the customer when a product is shipped
🔧 chore!: drop support for Node 6
BREAKING CHANGE: use JavaScript features not available in Node 6.
- ❌
🌟feat:ETLP-123:add some method
- 👍
🌟 feat: ETLP-123: add some method
ต้องมีบรรทัดว่าง คั่นระหว่าง description, body, footer
🐛 fix: ETLP-432: prevent racing of requests
Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.
Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
Reviewed-by: Z
Refs: #123
⏪️ revert: let us never again speak of the noodle incident
Refs: 676104e, a215868, COMMIT-ID
ใครที่ใช้ vscode สามารถใช้ Extension เสริม เช่น vscode-git-commit เรามี Config มาให้นำไปใช้กันเพียงนำไปเพิ่มใน settings (Wins + Shift + p
search User settings (JSON)
)
Preview
Go back and make multiple commits whenever possible
กลับไปแก้ไขและพยายามแบ่งออกให้เป็นหลาย commit เท่าที่จะเป็นไปได้ ประโยชน์ส่วนหนึ่งของ Conventional Commits คือการที่มันช่วยให้เราสามารถจัดการกับ commit และ PR (pull request) หรือ MR (merge request) ได้ดีกว่าเดิม
มันทำให้การทำงานแบบไม่มีการจัดการช้าลง แต่มันจะช่วยให้คุณทำงานได้เร็วขึ้นในระยะยาวกับหลาย ๆ project ที่มีส่วนร่วมจากหลาย ๆ คน
commit ที่มีชนิดเป็น fix จะถูกมองเป็น PATCH
ใน release ส่วน commit ชนิดที่เป็น feat จะถูกมองเป็น MINOR
release และ commits ที่เป็น BREAKING CHANGE
ไม่ว่าจะเป็นชนิดใดก็ตาม จะถูกมองเป็น MAJOR
release
ก่อนที่จะ merge หรือ release ความผิดพลาดนั้น แนะนำให้ใช้ git rebase -i
เพื่อแก้ไขข้อความใน commit ย้อนหลัง แต่ถ้าทำหลังจากที่ release ไปแล้ว การแก้ไขจะแตกต่างกันไปขึ้นอยู่กับ tool และวิธีการที่คุณใช้
ในสถานการณ์ที่แย่ที่สุด มันไม่ใช่วันสิ้นโลกถ้าคุณจะใส่ commit ที่ไม่สอดคล้องกับข้อกำหนดของ Conventional Commits มันมีความหมายง่าย ๆ คือ commit นั้นจะถูกมองข้ามไปถ้าใช้ tool ที่อ้างอิงตามข้อกำหนดนี้เท่านั้นเอง