Git commit best practices

General

Git commit best practices

This post explains how to write good git commit messages and how NOT to write bad git commit messages. Also, you will learn some more best practices related to committing your code changes to Git.

TLDR;

  • Use the imperative mood in the subject line
  • Capitalize the first letter in the subject line and do not end the subject line with a period
  • Limit the subject line to 50 characters
  • Separate subject from body with a blank line and wrap at 72 chars
  • Use git hooks to link to the task ticket
  • Make atomic commits
  • Commit often

Use the imperative mood in the subject line ( break at ~50 characters in commit subject )

Imperative mood means "written as if you are giving a command or an instruction"

Example: Close the window, Clean your plate, etc

Start the subject line with a capital letter and do not use a period at the end of the commit message.

A properly formed Git commit subject line should always be able to complete the following sentence: If applied, this commit will

For example:

  • If applied, this commit will Remove deprecated packages
  • If applied, this commit will Update core/cloud documentation
  • If applied, this commit will Release version 3.1.0

Write descriptive commit messages ( wrap at 72 characters in commit body )

The commit messages should say the context of what is changed. One word commit messages does not say anything. If you cannot convey what you want to say in a ~50 characters subject, the changes probably should not be in a single commit.

If you have to explain why the change is done and want to write the limitations in detail, write in the commit body. The body should be wrapped at 72 characters.

Ideal descriptive commit message with subject and body looks like this:

Change authorization method in frontend from cookies to tokens

The change in API was causing the failure of login to
frontend. So, login will not work anymore if we use
cookie for auth. Now the auth tokens are used with the
API request for the login.

If it is not necessary to write the body of the commit message in your case, make sure to write a clear and descriptive subject line.

Use the git hooks

In the project repository, in .git/hooks you will find the sample files to set up git hooks. Rename the commit-msg.sample file to commit-msg.

If your branch name is PROJECT-1245-feature-xyz, with the below commit-msg hook, every commit message will have the ticket ID in the prefix.

NOTE: In serious projects, it is always a best practice to name the branch starting with the ticket ID.

Example commit messages with the hook:

  • PROJECT-1245: Remove deprecated packages
  • PROJECT-1245: Release version 1.0

content of the hook commit-msg:

if [ -z "$BRANCHES_TO_SKIP" ]; then
  BRANCHES_TO_SKIP=(main)
fi

BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_NAME="${BRANCH_NAME##*/}"
BRANCH_ID="$(cut -d'-' -f2 <<<"$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/^/PROJECT-$BRANCH_ID: /" $1
fi

This might be useful because if you see any commit in the future, you can easily trace it back to the ticket and get more information on why it is done. However, this should not be an excuse to write short commit messages.

Commit often

Whenever you have something that works and does not break anything for anyone else, do a commit. If you make a LOT of changes and commit once, it might be harder to track what went wrong and where.

TIP: If you have a Pull Request ( PR ) pipeline set up, you can raise a draft PR. PR pipeline is run for every commit you make, and you exactly know what commit broke the pipeline.

Atomic commits

The atomic commit is a small commit that can't be broken up any further.

Three main features of atomic commits:

  • single irreducible unit
  • everything still works
  • clear and concise

Advantages:

  • spending a LOT less time in solving merge conflicts.
  • can review the code commit by commit.
  • reading commits will tell a story about what is done.
  • If your local git gets corrupted, uncommitted changes are not lost

Bad vs Good commit messages

badwhat's wronggood
updateshort, does not say anythingUpdate getting started documentation
renamed variablesnon-imperative moodRename variable cloud_host to cloudHost in API calls
bug fixDoes not say what bugFix bug of not changing to in-use status when some user is streaming
More changessays nothingRefactor service ABC for better readability
typosays nothingFix a typo in the error message of service ABC's save function
Fix a bug in frontend and refactor database-fetch file and add unit testlong and non-atomicCommit 1: Fix a bug in frontend button disable issue
Commit 2: Refactor database-fetch file for better readability
Commit 3: Add unit test for testing enable_connection

More Posts

Web of Things ( WoT ) Explained
General

The Internet of Things has revolutionized the way we interact with our devices, but it also brings new challenges in terms of interoperabili...

10 essential tips to speed up software development on Linux
General

Developers who always use Linux can not shut up about it because it is actually that good. It feels like you are coming out of the abstracti...

What is an RTOS?
Device Software

RTOS or a Real-Time Operating system is an operating system usually running on an embedded device that can run time-constrained applications...