All articles

Track Code Changes with Ticket IDs in Git Commit Messages

Stop maintaining file header changelogs. Use a simple Git commit-msg hook to enforce ticket IDs in every commit and build a traceable history automatically.

June 16, 2025 · 4 min read

A lot of us came from teams that used old-school Apex or Java file headers like:

/*
 * Author: Shivansh
 * Update Log:
 * 1. 2023-04-05 - Shivansh - Initial Development for PROJ-2345
 * 2. 2024-04-06 - Vishal - Development for PROJ-5678
 * 3. 2025-06-01 - Shivansh - bugfix for PROJ-7321
 */

You need to know why a particular change happened.

You look at class comments. You run git blame. You scroll through git log. You ask around on Slack. Someone replies: “Yeah, that was for PROJ-1234, I think.”

Most teams already live in their issue tracker — Jira, GitHub Issues, Azure Boards — that’s where the real story is:

  • Bug reports
  • Linked docs
  • Design approvals
  • Slack threads

Even our conversations usually start with: “What’s the ticket number?”

But our commit messages? Often vague. Detached. Easy to forget.

File headers worked — but they don’t scale

File headers with comments are not elegant, but they worked. Because they told you the why.

And that’s the point.

But it’s not enforced. Sometimes a dev feels changes are so minuscule, why bother adding to the log. Or they may add the wrong name. And at times it becomes so cluttered that half the screen is littered with modification logs.

Here’s a simple way to bring that clarity to your Git workflow: link one or more ticket numbers with a commit message and you can say goodbye to manually maintaining change logs.

But you may forget to include the ticket number in a commit message, or some devs do it while others don’t.

Enforce it with a commit-msg hook

To enforce this, use a commit-msg hook to enforce a ticket pattern — like PROJ-1234.

Create a folder .githooks, and create a file in it called commit-msg:

#!/bin/sh
PATTERN="PROJ-[0-9]{3,6}" # replace the value with your REGEX here
grep -Eq "$PATTERN" "$1" || {
  echo "Commit must include a ticket ID like PROJ-1234"
  exit 1
}

Change the regex pattern and message, give it permission to be executed, and point Git to the folder:

chmod +x .githooks/commit-msg
git config core.hooksPath .githooks

Now every commit can be traced. You can link tickets. You can cherry-pick with confidence. You can answer the one question that matters:

“Why did this change happen?”

Query the history

Any time you need the history, simply run:

git log --follow --pretty=format:"%ad | %an | %h | %s" --date=iso path/to/your/file

This returns something like the following, in reverse chronological order (most recent first):

2025-06-01 23:55:24 +0530 | Shivansh | 32e5265 | bugfix for PROJ-7321
2024-04-06 23:56:48 +0530 | Vishal   | 4bf3b8c | Development for PROJ-5678
2023-04-05 00:00:10 +0530 | Shivansh | 54deb19 | Initial Development for PROJ-2345

A note for Salesforce developers

If you’re a Salesforce developer like me and use the sf project generate command to create a new project (or use the VS Code extension), you may have Husky installed. Husky does a pre-commit hook to format files, so you can store your hooks in the .husky folder instead.

More Articles

Mar 14, 2026 10 min read

Claude Code in Action — A Practitioner's Take

I took Anthropic's official Claude Code course. Here's what changed how I work, where I disagree with the course, and the gaps you'll fill on your own.