Commit messages guide
A guide to understanding the importance of commit messages and how to write them well.
It may help you to learn what a commit is, why it is important to write good messages, best practices and some tips to plan and (re)write a good commit history.
What is a "commit"?
In simple terms, a commit is a snapshot of your local files, written in your local repository. Contrary to what some people think, git doesn't store only the difference between the files, it stores a full version of all files. For files that didn't change from one commit to another, git stores just a link to the previous identical file that is already stored.
The image below shows how git stores data over time, in which each "Version" is a commit:
Why are commit messages important?
- To speed up and streamline code reviews
- To help in the understanding of a change
- To explain "the whys" that cannot be described only with code
- To help future maintainers figure out why and how changes were made, making troubleshooting and debugging easier
To maximize those outcomes, we can use some good practices and standards described in the next section.
These are some practices collected from my experiences, internet articles, and other guides. If you have others (or disagree with some) feel free to open a Pull Request and contribute.
Use imperative form
# Good Use InventoryBackendPool to retrieve inventory backend
# Bad Used InventoryBackendPool to retrieve inventory backend
But why use the imperative form?
A commit message describes what the referenced change actually does, its effects, not what was done.
This excellent article from Chris Beams gives us a simple sentence that can be used to help us write better commit messages in imperative form:
If applied, this commit will <commit message>
# Good If applied, this commit will use InventoryBackendPool to retrieve inventory backend
# Bad If applied, this commit will used InventoryBackendPool to retrieve inventory backend
Capitalize the first letter
# Good Add `use` method to Credit model
# Bad add `use` method to Credit model
The reason that the first letter should be capitalized is to follow the grammar rule of using capital letters at the beginning of sentences.
The use of this practice may vary from person to person, team to team, or even from language to language. Capitalized or not, an important point is to stick to a single standard and follow it.
Try to communicate what the change does without having to look at the source code
# Good Add `use` method to Credit model
# Bad Add `use` method
# Good Increase left padding between textbox and layout frame
# Bad Adjust css
It is useful in many scenarios (e.g. multiple commits, several changes and refactors) to help reviewers understand what the committer was thinking.
Use the message body to explain "why", "for what", "how" and additional details
# Good Fix method name of InventoryBackend child classes Classes derived from InventoryBackend were not respecting the base class interface. It worked because the cart was calling the backend implementation incorrectly.
# Good Serialize and deserialize credits to json in Cart Convert the Credit instances to dict for two main reasons: - Pickle relies on file path for classes and we do not want to break up everything if a refactor is needed - Dict and built-in types are pickleable by default
# Good Add `use` method to Credit Change from namedtuple to class because we need to setup a new attribute (in_use_amount) with a new value
The subject and the body of the messages are separated by a blank line. Additional blank lines are considered as a part of the message body.
* and ` are elements that improve readability.
Avoid generic messages or messages without any context
# Bad Fix this Fix stuff It should work now Change stuff Adjust css
Limit the number of characters
It's recommended to use a maximum of 50 characters for the subject and 72 for the body.
Keep language consistency
For project owners: Choose a language and write all commit messages using that language. Ideally, it should match the code comments, default translation locale (for localized projects), etc.
For contributors: Write your commit messages using the same language as the existing commit history.
# Good ababab Add `use` method to Credit model efefef Use InventoryBackendPool to retrieve inventory backend bebebe Fix method name of InventoryBackend child classes
# Good (Portuguese example) ababab Adiciona o método `use` ao model Credit efefef Usa o InventoryBackendPool para recuperar o backend de estoque bebebe Corrige nome de método na classe InventoryBackend
# Bad (mixes English and Portuguese) ababab Usa o InventoryBackendPool para recuperar o backend de estoque efefef Add `use` method to Credit model cdcdcd Agora vai
Summarize changes in around 50 characters or less More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of the commit and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); various tools like `log`, `shortlog` and `rebase` can get confused if you run the two together. Explain the problem that this commit is solving. Focus on why you are making this change as opposed to how (the code explains that). Are there side effects or other unintuitive consequences of this change? Here's the place to explain them. Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary here If you use an issue tracker, put references to them at the bottom, like this: Resolves: #123 See also: #456, #789
Rebase vs. Merge
This section is a TL;DR of Atlassian's excellent tutorial, "Merging vs. Rebasing".
TL;DR: Applies your branch commits, one by one, upon the base branch, generating a new tree.
TL;DR: Creates a new commit, called (appropriately) a merge commit, with the differences between the two branches.
Why do some people prefer to rebase over merge?
I particularly prefer to rebase over merge. The reasons include:
- It generates a "clean" history, without unnecessary merge commits
- What you see is what you get, i.e., in a code review all changes come from a specific and entitled commit, avoiding changes hidden in merge commits
- More merges are resolved by the committer, and every merge change is in a commit with a proper message
- It's unusual to dig in and review merge commits, so avoiding them ensures all changes have a commit where they belong
When to squash
"Squashing" is the process of taking a series of commits and condensing them into a single commit.
It's useful in several situations, e.g.:
- Reducing commits with little or no context (typo corrections, formatting, forgotten stuff)
- Joining separate changes that make more sense when applied together
- Rewriting work in progress commits
When to avoid rebase or squash?
Avoid rebase and squash in public commits or in shared branches where multiple people work on. Rebase and squash rewrite history and overwrite existing commits, doing it on commits that are on shared branches (i.e., commits pushed to a remote repository or that comes from others branches) can cause confusion and people may lose their changes (both locally and remotely) because of divergent trees and conflicts.
Useful git commands
Use it to squash commits, edit messages, rewrite/delete/reorder commits, etc.
pick 002a7cc Improve description and update document title pick 897f66d Add contributing section pick e9549cf Add a section of Available languages pick ec003aa Add "What is a commit" section" pick bbe5361 Add source referencing as a point of help wanted pick b71115e Add a section explaining the importance of commit messages pick 669bf2b Add "Good practices" section pick d8340d7 Add capitalization of first letter practice pick 925f42b Add a practice to encourage good descriptions pick be05171 Add a section showing good uses of message body pick d115bb8 Add generic messages and column limit sections pick 1693840 Add a section about language consistency pick 80c5f47 Add commit message template pick 8827962 Fix triple "m" typo pick 9b81c72 Add "Rebase vs Merge" section # Rebase 9e6dc75..9b81c72 onto 9e6dc75 (15 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into the previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
Use it to clean up commits easily and without needing a more complex rebase. This article has very good examples of how and when to do it.
It is very useful to apply that commit you made on the wrong branch, without the need to code it again.
$ git cherry-pick 790ab21 [master 094d820] Fix English grammar in Contributing Date: Sun Feb 25 23:14:23 2018 -0300 1 file changed, 1 insertion(+), 1 deletion(-)
add/checkout/reset [--patch | -p]
Let's say we have the following diff:
diff --git a/README.md b/README.md index 7b45277..6b1993c 100644 --- a/README.md +++ b/README.md @@ -186,10 +186,13 @@ bebebe Corrige nome de método na classe InventoryBackend `` # Bad (mixes English and Portuguese) ababab Usa o InventoryBackendPool para recuperar o backend de estoque -efefef Add `use` method to Credit model cdcdcd Agora vai `` +### Template + +This is a template, [written originally by Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), which appears in the [_Pro Git Book_](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project). + ## Contributing Any kind of help would be appreciated. Example of topics that you can help me with: @@ -202,3 +205,4 @@ Any kind of help would be appreciated. Example of topics that you can help me wi - [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) - [Pro Git Book - Commit guidelines](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines) +- [A Note About Git Commit Messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
We can use
git add -p to add only the patches we want to, without the need to change the code that is already written.
It's useful to split a big change into smaller commits or to reset/checkout specific changes.
Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]? s Split into 2 hunks.
@@ -186,7 +186,6 @@ `` # Bad (mixes English and Portuguese) ababab Usa o InventoryBackendPool para recuperar o backend de estoque -efefef Add `use` method to Credit model cdcdcd Agora vai `` Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
@@ -190,6 +189,10 @@ `` cdcdcd Agora vai `` +### Template + +This is a template, [written originally by Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), which appears in the [_Pro Git Book_](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project). + ## Contributing Any kind of help would be appreciated. Example of topics that you can help me with: Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]?
@@ -202,3 +205,4 @@ Any kind of help would be appreciated. Example of topics that you can help me wi - [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) - [Pro Git Book - Commit guidelines](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines) +- [A Note About Git Commit Messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
Other interesting stuff
Any kind of help would be appreciated. Example of topics that you can help me with:
- Grammar and spelling corrections
- Translation to other languages
- Improvement of source referencing
- Incorrect or incomplete information