(ทำไมและยังไง) เติม [Story-ID] ด้านหน้า commit message อัตโนมัติ ด้วย git hooks (Git-flow + Jira-ID + Git hook)

Nitipat Wuttisasiwat (Ken)
3 min readJun 27, 2019

--

ตัวอย่างผลลัพธ์ commit message ที่มี [story-id] ต่อหน้าให้อัตโนมัติ

git commit -m “commit message” -> “[STORY-13] commit message”
หรือจะใช้ Git UI อย่าง Source tree, GitKraken ในการ commit ก็ได้

หัวข้อนี้จะพูดถึงอะไรบ้าง ?

  1. เกริ่นนำ รูปแบบการทำงานที่เหมาะสมกับการใช้งานของบทความนี้
    1.1 Git-flow คืออิหยัง
    1.2 JIRA ID/Story-ID
    1.3 ตัวอย่างการใช้งาน Git-flow + Story-ID
    1.4 ทำไมต้องตั้งชื่อ [STORY-ID] ก่อนหน้า commit message
  2. การ config git hook ให้ format ชื่อของ branch (หรือ story-id) มาต่อด้านหน้าอัตโนมัติ
    2.1 git hooks คืออะไร
    2.2 โค้ดสำหรับ config git hook ให้ prepend commit message อัตโนมัติ
  3. โค้ดสำเร็จ ก๊อปแปะ ใช้งานได้เลย สำหรับคนที่เข้าใจเนื้อหาข้อ 2 อยู่แล้ว

1.

เกริ่นนำ แปปนะ ใครเข้าใจแล้วก็ข้ามลงไปเลย

ปัจจุบันการใช้ git เพื่อจัดการ version ของ source code นั้นมี “Branching convention” หรือแนวทางการแตกกิ่ง ที่แตกต่างกันหลากหลาย ใน blog นี้จะยกตัวอย่าง convention ของ Git-flow + Jira

1.1 Git-flow

Git-flow เป็น extension ชนิดหนึ่งที่มีรูปแบบการจัดการของชนิดกิ่งเป็น 5 ชนิด (master, develop, release, hotfix และ feature) โดยเราจะไม่ลงรายละเอียดของโมเดลนี้ ถ้าสนใจให้ไปอ่านเพิ่มเติมที่ https://danielkummer.github.io/git-flow-cheatsheet/

ในบทความนี้เราจะเจาะจงลงไปที่ branch ชนิด feature
“Feature/” branch มักจะถูกใช้เรียกเมื่อกิ่งนี้ใช้ในการพัฒนา งานใหม่ๆ หรือ “Story” ใหม่ๆ ยกตัวอย่างเช่น feature/login, feature/logout เป็นต้น

1.2 Jira ID/Story ID

ในการพัฒนาซอฟต์แวร์ ถ้าเรานึกภาพว่าเราต้องการพัฒนาแอปพลิเคชันที่มี ฟีเจอร์ 1,000 อัน มันคงจะลำบากมากๆถ้าเราจะต้องมาคอยคิดชื่อให้แต่ละฟีเจอร์

มึงๆ งานนี้เรียกฟีเจอร์ไรดีวะ automatically-upload-picture-when-enter-thai-id-card ดีมั้ย

ไหนจะปัญหาคิดไม่ออกแล้ว จำชื่อไม่ได้แล้ว บางฟีเจอร์ดั๊นน ยาวเกินไปอีก
เลยมีคนเกิดแนวคิดประยุกต์เข้ากับการใช้ Software Management Tool ขึ้นมาช่วย เช่น Jira

ภาพ Jira ที่มีตัวอย่างการอธิบายงานต่างๆอยู่ ขอบคุณรูปภาพจาก https://developer.atlassian.com/server/jira/platform/developing-for-the-jira-project-centric-view/

ภาพข้างต้นเป็นการแสดงถึงงานที่ถูกแบ่งย่อยออกมาให้ทำ ไม่ว่าจะเป็นการใช้ Development life cycle แบบไหนก็แล้วแต่ เช่น Agile, Scrum, Waterfall โดยแต่ละงานที่ถูกสร้างขึ้นมาจะเรียกว่า Ticket

ซึ่ง Ticket ไม่ได้หมายถึงแค่งานที่จะต้องทำใหม่เท่านั้น มันรวมถึงบัคที่เกิดขึ้นรอแก้ งานเก่าที่เสร็จแล้วแต่ต้องถูกปรับแก้บางส่วน ฯลฯ

โดยถ้าสังเกตจากภาพงานทุกงานจะมี auto-increment number ให้เช่น JIRA-1 JIRA-2 JIRA-3 ซึ่งในบทความนี้จะขอเรียกหมายเลขข้างต้นนี้ว่า “Story-ID” (บางที่อาจจะเรียก Ticket-ID, Jira-ID, etc.)

1.3 ตัวอย่างการใช้งาน Git-flow + Story-ID

แสดงชื่อ Branch ที่ถูกแตกออกไปด้วย convention “feature/[Story-ID]

งานในหมวดที่เป็นการสร้างใหม่ หรือเรียกว่าฟีเจอร์ ก็จะถูกใช้ convention ใน Git-flow ว่า “feature/…” ซึ่งก็จะนำมาประยุกต์โดยการต่อท้ายด้วย Story-ID ที่ถูก generated จาก Jira tool

1.4 ทำไมต้องตั้งชื่อ [STORY-ID] ก่อนหน้า commit message

ในเหตุการณ์จริงสมมติว่ามี branch ที่ถูกทำงานอยู่พร้อมๆกัน 4 branch ในแต่ละ branch เกิด commit ขึ้นประมาณ 5–20 commits
ถ้าสมมติว่า merge รวมกัน จะเกิดปัญหา แบบนี้

commit ใครก็ไม่รู้ เรียงกันมั่ว trace ยากมากๆ

commit จากทั้ง 4 branch จะถูกนำมาเรียงตามลำดับการเกิดขึ้น (timestamp) แล้วเมื่อเราต้องการจะ trace กลับไปปัญหาคือ ยากและค่อนข้างเสียเวลา

ในบางการทำงานจึงนิยมที่จะต้องใส่ `[STORY-ID] Commit message`
Story-ID ต่อหน้าชื่อคอมมิทเพื่อง่ายต่อการแกะรอยย้อนกลับ

แบบนี้เป็นต้น

คราวนี้ทุกครั้งที่เรา commit ก็ต้องมานั่งใส่ [STORY-ID] ต่อหน้าทุกครั้งไม่ว่าจะเป็น
ใน terminal เช่น git commit -m “[STORY-ID] modify core code”
หรือแม้แต่ UI เองก็ตาม
…. ซึ่งเราสามารถ automate มันได้ !!

2

ถึงเวลาเข้าเนื้อ ที่ไม่ใช่น้ำ

2.1 Git hooks คืออะไร

“Git hook คือชุดของคำสั่งที่ Git จะเรียก ก่อนหรือหลังคำสั่งหลักใดๆ เช่น commit, push”

Git hooks เป็นสิ่งที่ติดตัวมากับ Git อยู่แล้วไม่ต้องไปดาวโหลดอะไรมาลงเพิ่มและ Git hooks นั้นเป็นฟีเจอร์ที่จำทำงานแบบ local หรือเฉพาะเครื่องของคนๆนั้นเท่านั้น

ซึ่งในบทความนี้เราจะเจาะลงไปใช้ hook ที่ชื่อว่า “prepare-commit-msg” ซึ่งเป็น hook ที่จะถูกเรียกใช้หลังจากที่เราสั่ง commit -m หรือใส่ message นั่นเอง
โดยที่ hook นี้จะสามารถนำ message ที่เราใส่ขึ้นมา modify ก่อนที่จะทำการเขียนลงไปได้

2.2 โค้ดสำหรับ config git hook ให้ prepend commit message อัตโนมัติ

ขอขอบคุณโค้ดจาก https://gist.github.com/bartoszmajsak/1396344

#!/bin/bash
if [ -z "$BRANCHES_TO_SKIP" ]; then
BRANCHES_TO_SKIP=(master develop test)
fi
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_NAME="${BRANCH_NAME##*/}"
BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$")
BRANCH_IN_COMMIT=$(grep -c "\[$BRANCH_NAME\]" $1)
if [ -n "$BRANCH_NAME" ] && ! [[ $BRANCH_EXCLUDED -eq 1 ]] && ! [[ $BRANCH_IN_COMMIT -ge 1 ]]; then
sed -i.bak -e "1s/^/[$BRANCH_NAME] /" $1
fi

สามารถ copy code ด้านบนไปวางไว้ยัง folder “.git/hooks/prepare-commit-msg.sh” ของโปรเจคและใช้งานได้เลย

3.โค้ดสำเร็จ ก๊อปแปะ ใช้งานได้เลย สำหรับคนที่ไม่อยากทำเอง

  1. เปิด terminal ขึ้นมาแล้วทำการ cd ไปยัง root ของโปรเจคที่ต้องการจะติดตั้ง
  2. ทำการแปะโค้ดข้างล่างนี้และกด enter
curl -O https://raw.githubusercontent.com/kennaruk/git-hook-sandbox/master/prepare-commit-msg/prepare-commit-msg-setup.sh
chmod +x prepare-commit-msg-setup.sh
./prepare-commit-msg-setup.sh
rm ./prepare-commit-msg-setup.sh
chmod +x ./.git/hooks/prepare-commit-msg

3. Enjoy auto prepended commit!

ใครที่สนใจโค้ดหรือข้อมูลเพิ่มเติมไปดูได้ที่
https://github.com/kennaruk/git-hook-sandbox/tree/master/prepare-commit-msg

หรือถ้ามีข้อสงสัย ก็สามารถคอมเมนต์ไว้ใต้ story นี้ได้เลย!

--

--

Nitipat Wuttisasiwat (Ken)

Innovation Engineer @KBTG, Doing full-stack development both web and Flutter