Chapter 2.3 โ€” Fix Commit Message โ€” amend rewriteโ˜• 14 min read

Fix Commit Message โ€” amend rewrite

Ganda message = confused team. Conventional Commits use karo: type(scope): subject. Aur pushed commit ka message KABHI mat badlo!

01Fixing a Bad Commit Message

We have all done it โ€” typed git commit -m "asdfghjkl" in a rush, or git commit -m "fix" without explaining what was fixed. The commit is done, the message is garbage, and now your team has to decipher it.

git commit --amend -m "new message" replaces the last commit message directly. No editor, no fuss โ€” just a clean fix.

git commit --amend (without -m) opens your configured text editor with the old message, ready for you to rewrite. Better for longer, more detailed messages.

A commit message is documentation. It tells your team WHY a change was made. Six months from now, when someone runs git blame, your message should explain the reasoning โ€” not just repeat "fix".

Conventional Commit format: type(scope): description (e.g., feat(auth): add login page). This standard makes history searchable and changelogs automatic.

Like --no-edit from Chapter 2.2, amending the message creates a NEW commit with a NEW SHA. The old commit is gone. This is a rewrite, not an edit.

# The terrible commit
git commit -m "asdfghjkl"

# Fix it directly
git commit --amend -m "feat: add user authentication"

# Fix it in your editor (for longer messages)
git commit --amend
# Opens editor with old message ready to edit

# Multi-line message directly
git commit --amend -m "feat: add authentication" -m "Implements JWT-based login and logout with token refresh."
Amending a message rewrites history. The old commit hash is replaced by a new one. This is fine on your local machine before pushing. But on a shared branch, it creates problems. The golden rule: never rewrite pushed history.
02Conventional Commits โ€” Structure Matters

A commit message without structure is noise. Conventional Commits give your team a shared language for describing changes.

Standard format: type(scope): subject

Types:

  • feat โ€” new feature for the user
  • fix โ€” bug fix for the user
  • docs โ€” documentation changes
  • style โ€” formatting, missing semicolons, no code change
  • refactor โ€” code restructure without changing behavior
  • test โ€” adding or updating tests
  • chore โ€” maintenance, build, CI, dependencies

Scope is optional but recommended: feat(auth):, fix(api):, docs(readme):

Subject line rules: max 50 characters, imperative mood ("add" not "added"), no period at end.

Body (optional): wrap at 72 characters, explain WHY, not HOW.

Breaking changes: feat!: new API or add BREAKING CHANGE: in footer.

# BAD messages
git commit -m "fix"
git commit -m "update"
git commit -m "WIP"
git commit -m "changes"
git commit -m "Fixed the thing that was broken yesterday"

# GOOD messages (Conventional Commits)
git commit --amend -m "feat(auth): add JWT login"
git commit --amend -m "fix(api): handle null response in user endpoint"
git commit --amend -m "docs: update API installation guide"
git commit --amend -m "refactor(utils): extract date formatting helper"
git commit --amend -m "chore: upgrade to Node 18"

# With body
git commit --amend -m "feat(auth): add JWT login" -m "The previous session-based auth was causing scalability issues. JWT allows stateless authentication."
๐Ÿ’ก Pro Tip: Imperative mood means writing "add" instead of "added", "fix" instead of "fixed". Think of it as a command: "This commit will add feature X" or "This commit will fix bug Y". Git itself uses imperative in its auto-generated messages like "Merge branch X".
03Using the Editor for Multi-Line Messages

Running git commit --amend without -m opens your default text editor. This is the better approach for longer messages with a subject and body.

The editor shows the old commit message โ€” you modify it, save, and close. The amend is done.

To change your editor:

  • git config --global core.editor "code --wait" โ€” VS Code (recommended)
  • git config --global core.editor "nano" โ€” Nano (beginner friendly)
  • git config --global core.editor "vim" โ€” Vim (advanced)

In the editor, you can write a proper multi-line commit message: first line is the subject (under 50 chars), blank line, then the body explaining the WHY.

Abort the amend: if you close the editor without making changes, the amend is cancelled. Git checks if the message was modified.

# Set your preferred editor
git config --global core.editor "code --wait"   # VS Code
git config --global core.editor "nano"           # Nano (beginner friendly)
git config --global core.editor "vim"            # Vim (advanced)

# Open amend in editor
git commit --amend
# Editor opens with:
#
# asdfghjkl
#
# # Please enter the commit message for your changes.
# # Lines starting with '#' will be ignored.
#
# Replace "asdfghjkl" with your proper message:
#
# feat(auth): add login endpoint
#
# Implements POST /api/auth/login with JWT generation.
# Save and close the editor to complete the amend.
VS Code users: The --wait flag is critical. Without it, Git thinks the editor closed immediately and the amend fails. code --wait tells Git to wait until you close the VS Code tab before proceeding. This applies to any GUI editor โ€” Sublime uses subl --wait, Atom uses atom --wait.
04The Golden Rule โ€” Never Rewrite Pushed Messages

Changing a commit message changes the SHA hash, just like amending content. The message is part of what gets hashed โ€” change it, and you get a completely different commit.

If the commit is already on a shared remote, changing the message creates history divergence. Your teammates still have the old commit. You now have a new one. The histories no longer match.

Even a "small message fix" on a pushed commit requires force push, which is dangerous. It overwrites the remote history and can lose other people's work.

The rule: If it is pushed and shared, leave the message alone. Add context in a future commit or in the PR description.

Exception: Your own feature branch that no one else has pulled. Even then, use --force-with-lease instead of --force.

# SAFE: Rewriting message on local commit
git commit -m "fix stuf"
# Realized it is a bad message...
git commit --amend -m "fix(api): handle timeout on user endpoint"
# Not pushed yet, so this is perfectly safe.

# DANGEROUS: Rewriting message on pushed commit
git push origin feature
# "I made a typo in the commit message..."
git commit --amend -m "fix(api): handle timeout"  # SHA changes!
git push origin feature
# ERROR: rejected. Requires force push.

# If you absolutely must on your own branch:
git push --force-with-lease origin feature
# But warn your team first!
Even a message change is a history rewrite. The SHA hash includes the commit message. Change the message = change the hash = new commit. On shared branches, this is just as dangerous as changing commit content. Think twice before amending anything that has been pushed.
05Prevention โ€” Better Messages First

You can prevent bad commit messages before they happen using Git hooks and tools. Prevention is better than amendment.

The commit-msg hook runs after you write a message but before the commit is created. If the hook exits with a non-zero code, the commit is rejected. This is where you validate message format.

commitlint enforces Conventional Commits automatically. It checks every message against your configured rules.

commitizen provides an interactive prompt โ€” instead of typing git commit -m, you run git cz and it walks you through type, scope, subject, and body step by step.

Even without tools, you can build the habit: always write type(scope): subject. After a few weeks, it becomes muscle memory.

# Manual check: always review your last commit
git log -1 --pretty=format:"%s"

# Quick amend shortcut if you notice a typo
git commit --amend -m "$(git log -1 --pretty=format:'%s' | sed 's/feat/fix/')"

# Using commitizen (if installed)
git cz  # Interactive prompt for conventional commits

# Simple commit-msg hook to enforce format
# .git/hooks/commit-msg
# Check that message starts with feat|fix|docs|style|refactor|test|chore
# Reject the commit if format is wrong
๐Ÿ’ก Git Hooks: Hooks are covered in detail in Stage 8. For now, know that .git/hooks/commit-msg is a script that runs before every commit is finalized. It receives the commit message file as an argument and can validate, modify, or reject the message. This is how teams enforce message standards automatically.

Lo kar liya โ€” Key Points:

  • โœ… git commit --amend -m "new message" directly replaces the last commit message
  • โœ… git commit --amend without -m opens your text editor to modify the message interactively
  • โœ… Good commit messages follow Conventional Commits: type(scope): subject (e.g., feat(auth): add login)
  • โœ… Subject lines should be under 50 characters, in imperative mood, with no trailing period
  • โœ… Changing a commit message changes the SHA hash โ€” never amend messages on pushed, shared commits
  • โœ… Use core.editor config to set your preferred editor for amending messages
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase