Post cover image provided via xkcd
Git commits are one of the most underrated features of Git. Pause for a moment and think;
When was the last time you had to revert your code to an earlier point in time?
Did you have a hard time finding that commit that messed up your code?
Was that because of unclear, mixed commit messages?
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:
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;
What did you change in each file? What classes are relevant to the sub-task functionality you worked on?
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):
- feat: a new feature
- fix: a bug fix
- docs: changes to documentation
- style: formatting, missing semi colons, etc; no code change
- refactor: refactoring production code
- test: adding tests, refactoring test; no production code change
- 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)
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.
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.
Isn't the author already recorded as part of the commit anyway?
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!
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'
Cool, that also works like a charm, especially for short commits. On larger ones, you might need to add multiple lines ;)
or split up the long commit into several short ones :)
Of course! Just keep making sure that you can easily navigate through the commit history.
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.
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.
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
My commit message workflow
Shreyas Minocha ・ Jun 22 '18 ・ 4 min read
Thanks for the comment and the reference, Vinay!
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 historyIt'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:
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.
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.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,
Cheers
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 ;)
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
Nice addition, Jakob!
Personally I (definitely not alone in this) found this guide compelling and informative, and I try to follow the Imperative Title, Explanatory Details pattern.
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.
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.
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.