DEV Community

Cover image for Git commits: An Effective Style Guide
Paul Isaris
Paul Isaris

Posted on • Edited on

Git commits: An Effective Style Guide

Post cover image provided via xkcd

Git commits are one of the most underrated features of Git. Pause for a moment and think;

  1. When was the last time you had to revert your code to an earlier point in time?

  2. Did you have a hard time finding that commit that messed up your code?

  3. Was that because of unclear, mixed commit messages?

  4. When that commit was found, did you also realize that you included several file changes in that particular commit, resulting in a headache when trying to rebase back to that commit?

Congratulations, you just incapacitated one of the strongest features of Git:

Code versioning & history!

The importance of keeping commits clean and tidy

As a developer, one of the most difficult tasks that you will stumble upon, is communication. Communication with other developers, with clients, with managers, but also communication with the future you.

Having a clean git commit messages history means that at any time in the future you will be able to revise what you changed in the code, what functionality parts were removed and what bugs were fixed.

By running git log you will be able to view a logical flow of messages that alone explain the whole code history of the application.
You can also run git log --pretty=oneline to view a more dense version of git log.

How to organize a commit message

If you use a Project management tool like Jira, Asana, Trello or other, and follow a task-breakdown project management flow like Scrum or Kanban, you will have all your tasks in one place, tidy and organized.

Your goal should be to have each commit characterize a corresponding sub-task. No more git commit -m "Added code", git commit -m "Added CSS" or git commit -m "bugfix".
These commits are untraceable and you will never be able to use them in the future.

So, why having them in the first place?

When you have changed a bunch of classes and you are ready to commit the code, take a moment and think;

  1. What did you change in each file? What classes are relevant to the sub-task functionality you worked on?

  2. How is your app affected and what breaking changes did you introduce to the code?

Following a clean message style

By choosing a style and sticking to it, you bring your code to another level.

Other developers will be able to read your message history like a novel and they might never have to look at the actual code (which will save them much time).

You will also force yourself to commit what matters, not what is convenient at the current moment.

Finally, the style guide

Message Structure

A clean commit message should consist of three distinct parts separated by a blank line: the title (which describes the type of code change), and a descriptive body with optional messages about the task following or the issue tracker id (footer).

The layout should look like this:

commit type

body (changes, links, attributions, etc)

issue tracker id (for reference)

The commit type

It can be an abbreviation of what the commit actually is. For example (taken from Udacity's commit style guide):

  1. feat: a new feature
  2. fix: a bug fix
  3. docs: changes to documentation
  4. style: formatting, missing semi colons, etc; no code change
  5. refactor: refactoring production code
  6. test: adding tests, refactoring test; no production code change
  7. chore: updating build tasks, package manager configs, etc; no production code change

The body

Anything that the commit changed on the code. It can be a description of the functionality added, a description of the task completed, or the steps of a bug reproduction and solution.

When composing the body, try to be as detailed as possible. Think that there is a high chance that you will be reading this commit message two years from now. What would you like to communicate to your future self about?
You can add bullet points, lists, links to Stackoverflow answers and links to your issue tracker.

Conclusion

Being able to compose meaningful Git commits will not only make you likeable to other developers that will read your commits.
It will also make you a better writer, as well as more analytical and clean code - oriented.

Think about your future self. Write better commits, today!

References:
Udacity Git Commit Message Style Guide

Top comments (28)

Collapse
 
andrespineros profile image
Andrés Felipe Piñeros

I saw something a co-worker does and I really liked it.

It is as simple as addind the Jira issue number and the short name of the person that did the commit.

Like "841-RickM-bug fixed bug blah blah"

Reading commits from the develop and master branch is pure joy this way. Like, everything makes sense.

Collapse
 
moopet profile image
Ben Sinclair

Why would you add the user's name? That only takes up room in the short version of the commit message, and you can see their name in the log anyway.

Collapse
 
mvz profile image
Matijs van Zuijlen

Isn't the author already recorded as part of the commit anyway?

Collapse
 
scottharrisondev profile image
Scott Harrison

We use BitBucket and Jira and when you add the issue number to the commit it links it in Jira too so you can go directly to the commit in BitBucket. Pretty cool stuff!

Collapse
 
jackedwardlyons profile image
Jack Lyons

Adding the username and / or trello/jira id/hash to your git branch is also pretty helpful in a team environment.

Eg, instead of 'new-bug-fix' ... you can write 'jlyons-idea1234-new-bug-fix'

Collapse
 
pavlosisaris profile image
Paul Isaris

Cool, that also works like a charm, especially for short commits. On larger ones, you might need to add multiple lines ;)

Collapse
 
alainvanhout profile image
Alain Van Hout

or split up the long commit into several short ones :)

Thread Thread
 
pavlosisaris profile image
Paul Isaris

Of course! Just keep making sure that you can easily navigate through the commit history.

Collapse
 
scottharrisondev profile image
Scott Harrison

Great article Paul!

I see you value a more fully featured, descriptive commit message. I've worked with a few developers who really push for short, punchy commit messages of <40 characters. I guess the logic is that it will be quick and easy to scan in future but in my opinion, often times you just can't convey what you need to convey in that short of a message.

Another thing I would say is it's important to know when to put something in a commit message and when to put it in project documentation. Sometimes I'll find myself writing something in the commit message and I'll read it back and realise it's much better suited to go in the README.md or similar.

Collapse
 
stecman profile image
Stephen Holdaway

Ideally you'd do both: a concise commit subject that summarises the whole change, and a commit body that explains the why of your change. The body is something people will rarely read, but they'll really appreciate it when it answers their questions (they've likely come to your commit message to clarify something).

eg. this commit.

Collapse
 
vinayhegde1990 profile image
Vinay Hegde

Excellent article, Paul!

Writing a meaningful git commit message is a good practice because it not only helps in debugging issues later (especially if it's been caused by one's own git commit) but also is one form of effective documentation that can be referred by anyone (e.g: new team-members) to get up-to speed on a project.

While I'm sure there are numerous articles on the internet towards this, here's one I found to add more detail

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for the comment and the reference, Vinay!

Collapse
 
stecman profile image
Stephen Holdaway • Edited

Nice post, Paul! I've been trying to work out for a while how to introduce developers to using Git in its full capacity, but it's a bit of a chicken and egg problem:

  • Without writing good commit messages, there's no reason to look at blame/history, since it doesn't have anything to offer

  • If you're not looking at the history, there's no reason to write good commit messages, and there's no reason to use rebasing to keep a clean history (eg. squashing extraneous "fix" commits)

  • Without a clean history, tools like git bisect become more pain than it's worth to use, so you don't work with the history

It's surprising that developers, who generally thrive on learning how things work, don't progress quickly past the "Git is Ctrl-S for code" stage:

Example of a bad history

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for your response Stephen, I know exactly what you mean. I indulge to the same "fast git commit" thing many times. Unfortunately, developers don't like to adhere to a new way of doing a certain thing "just because" someone told them.
If they see value in it, then they will do it.
So, if they stumble upon a situation where they want to rollback to a certain commit and spend hours finding it, then they will cahnge their minds.
So, the only way of getting them to use a new git style is actually to ask them for baby, incremental steps.
For example, they could try adding the issue tracker id in their commit messages, for a month.
Then, they could also tag the major commits so that there is a way to rollback to a previous version, easily.
These incremental small changes will result in them not complaining about drastically changing their way of work.

Collapse
 
l_giraudel profile image
Loïc Giraudel

Really nice article, thanks a lot Paul!

I would have put the issue tracker id on the first line (ideally at the beginning) to easily find commits related to a specific feature/issue, it's usually the starting point of investigations.

I really like the commit type, I'll try to use it in my own commits, but I disagree with the "test" type. Tests should be added in the commit containing the feature/fix code because if you put tests code in a commit before feature code, a git bisect can stop between both commits and lead to broken unit tests. And if you put tests code after the feature code, you can forgot to revert the tests when you need to revert the feature, which will break tests too.

The more complex step when doing small and smart commits is to encourage the rest of the team to do the same. This methodology takes time and developers don't often see the real advantage to do it (we don't need to git bisect every day). I think the best argument is about Pull Requests: with small and specific commits, rather than reading the whole change which is sometimes really hard, reading commit by commit and skipping the less interesting ones leads to more valuable code reviews. My Pull Requests are often paired with a long description linking to the important commit to read.

Collapse
 
rafalpienkowski profile image
Rafal Pienkowski

Very nice article Paul.

I agree that commit message is essential. On first glance, it tells us a lot about commit itself, and it should be made neatly. Fortunately, nowadays most of IDE has excellent support for git. I prefer to look directly into the code and later search for the particular commit. So I omit the stage of looking through commit messages at all. I don't think that my way is the best one, but it helps in case of the mess in commit messages.
I think that more important than meaningful commit message is proper commit body. I mean, devs should avoid committing all changes in one commit and split at every available place. Creation of a commit cost as a little time but can save a lot of time in future, especially when we would like to revert some evil commit from our branch. It'd be much more difficult if we have multiple functionalities changed in one commit. This is a real nightmare!

So,
Keep calm and commit

Cheers

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for your response, Rafal! Totally agree with you on this.
Code readability is much more important than commit messages, and should be first priority ;)

Collapse
 
attkinsonjakob profile image
Jakob Attkinson

I believe there's at least one more thing missing from the Udacity's commit style guide. There are situations when you improve some existing code by adding a new behavior. (e.g. automatically check a checkbox when a date field is set).

Therefore, I'd probably add "Improve" there too, as some things don't fall into fixing, adding a new feature or refactoring code category

Collapse
 
pavlosisaris profile image
Paul Isaris

Nice addition, Jakob!

Collapse
 
dangolant profile image
Daniel Golant

Personally I (definitely not alone in this) found this guide compelling and informative, and I try to follow the Imperative Title, Explanatory Details pattern.

Collapse
 
mvz profile image
Matijs van Zuijlen

I'm all for good, structured commit messages, but do not see the point of the commit type. It leaves even fewer characters for a meaningful title, and creates friction by being one more thing to think about.

Collapse
 
pavlosisaris profile image
Paul Isaris

Well, of course it can be omitted if you think that it does not improve commit readability, but it sure is a helpful way of filtering out the commits of a certain type.

Collapse
 
rkfg profile image
rkfg

I think all of this could be omitted when you've just started a new project and at the early stages. The reasoning is simple: you need small, atomic and well-commented commits to find regressions (mostly), admire the history and to make merges/rebases easier. This is not needed when there's not much code and you only write the most basic subsystems. Actually, I'd argue that making verbose and small commits that early is counterproductive as it distracts from the flow. It might be wrong for big teams and huge tasks but I'm sure it applies to pet and medium-sized projects. My own projects usually start with a big "Initial commit" and a set of huge commits after that, mostly described as "WIP" or so.

Of course, when the groundwork is set the commits should become smaller and more feature/bugfix oriented. It can also be used as a good rule of thumb telling you the project has probably become an MVP or an alpha and is ready to be shown to somebody.