How to write comments to commits

Original author: Chris Beams
  • Transfer


Preface from the translator


Over the years, software development, being a member of many teams, working with different good and experienced people, I often watched (and what a sin to conceal, up to a certain point - created) the same problem - the total mess in the repository. Everyone wrote comments on commits in their own style (and it’s good, if it’s always in one); half of the comments were useless (from the category “ this is a bridge ”), half of the remaining half was barely understandable.

And then at one point, I saw this article, which I finally got my hands on. Only 7 simple and short rules, and - lo and behold - looking at the history of commits was not only useful, but also pleasant. Nothing revolutionary, everything is pretty obvious, but it is formulated and summarized just fine.

I want to note that this is a 2014 article. Some not very relevant things mentioned by the author, could lose relevance, but the essence of the article - not at all.

Introduction: Why Good Comments Are Important


If you look at a random Git repository, you will most likely find that there is a mess in the history of commits. For example, take a look at these pearls from the time when I started committing to the Spring repository:
$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"
e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement () The classloader hacking causes subtle downstream effects, breaking unrelated tests. It is not necessary to ensure that the test method is still valid.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated the ConfigurationPostProcessorTests
147709f Tweaks to package-info.java files
22b25e0 Consolidated Utilities and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing
Horror. Compare with these more recent commits in the same repository:
$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"
5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage
Which option would you prefer?

The first differ in length and style, the second - concise and homogeneous.
The first is obtained by itself, the second is written consciously.

And although the history of commits of many repositories looks like the first option, there are exceptions. Excellent examples are the Linux kernel and Git itself . Also look at Spring Boot or any other repository that Tim Pope works on .

Participants in these projects know that a well-written comment on a commit is the best way to tell the context of the changes made to other developers (as well as to themselves in the future). Differences in revisions show thatchanged, but only a comment can clearly explain why . Peter Hutterer said it well :
Restoring the circumstances of writing code is a waste of time. We cannot completely avoid it, so our efforts should be focused on minimizing these costs. This is what comments on commits are needed for. Therefore, they show whether the programmer works well in a team.
If you haven't really thought about what a high-quality commit comment should be like - you probably haven't used git log and similar tools too often . There is a vicious circle: since the history of commits is unstructured and heterogeneous, they do not use it and do not pay attention. And due to the fact that it does not use and do not pay attention, it remains unstructured and heterogeneous.

But a well-designed repository history is a beautiful and useful thing. Commands git blame , revert , rebase , log , shortlog come to lifeand others. It makes sense to look at other people's commits and pull-requests, and, suddenly, without the help of their authors. To understand why something happened [in the code] months or years ago becomes not only possible, but also convenient.

The long-term success of the project depends (among other things) on how convenient it is to maintain it, and the history of commits is one of the most powerful tools of the maintener. It is worth spending time learning how to maintain order in it. At first this may cause some inconvenience, but then it will become a habit and, in the end, will become a source of pride and productive work for all participants.

This article covers only the most basic component of a good history, namely how to write a comment to a separate commit. There are other important things, such as combining commits, which are not covered here.

In most programming languages, there are well-described generally accepted conventions that form a distinctive [coding] style, such as variable names, formatting rules, and so on. Of course, there are different versions of such agreements, but most developers are of the opinion that choosing one option and following it is much better than a mess when everyone writes in his own style.

The command's approach to the description of commits should be exactly the same. In order for the repository history to be useful, the team must agree on at least the following three points.

Style. Markup syntax, indents, line breaks, grammar, capital letters, punctuation. Always check your spelling and write as easily as possible. As a result, you will get an amazingly solid commit history, which is not only pleasant to read, but which will actually be read regularly.

Content. What kind of information should (if any) should be contained in the comment body? Why shouldn't it be there?

Metadata. How should I refer to task IDs, pull request numbers, etc.?

Fortunately, there are already agreements on writing meaningful commentary. In fact, they stem in part from the way some Git commands work. You do not need to reinvent the wheel. Just followseven rules below - and you will be one step closer to the history of commits, worthy of a professional.

Seven rules of a class comment to commit


Remember: All this has already been said before .
  1. Separate header from body with empty line.
  2. Limit the header to 50 characters.
  3. Capitalize title
  4. Do not put a period at the end of the title
  5. Use the imperative in the title
  6. Go to the next line in the body of 72 characters
  7. In the body, answer the questions what and why , and not how

For example:
Summarize changes in 50 characters or less.
Then explain them in more detail, if necessary. Follow
line breaks of approximately 72 characters. In some situations
The first line of commenting is considered its title, and all 
the rest is in the body. It is extremely important to separate clothe one from another.
empty string (if the message has a body at all, of course);
various tools like `log`,` shortlog` and `rebase` will not understand
you, if the title and body are not separated.
Explain here what problem this commit solves. Give it to
more attention to why you made these changes, and not to 
exactly how you did it (this will explain the code for you).
Are there any side effects or other non-obvious effects on 
these changes? If yes, it needs to be explained here.
Paragraphs are separated by blank lines.
 - Can make bulleted lists
 - Usually an asterisk or 
   a dash with a space in front of them; but there are different agreements
If you have a bug tracker [or project management system],
Put links to tasks at the end of the text like this:
Resolved: # 123
See also: # 456, # 789

Original
Summarize changes in around 50 characters or less
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. The first line is treated as the
the body of the body. The
blank line
you omit the body entirely); various tools like `log`,` shortlog`
and `rebase` can get confused if you run the two together.
Explain the problem Focus on why you
the code explains that.
Are there side effects or other
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



1. Separate the title from the body with an empty line.


From the manual to the git commit command :
Although this is not necessary, it is a good idea to start a comment to a commit with one short (less than 50 characters) line summarizing the changes made, then an empty line and then a more detailed description. Text up to the first blank line in a comment is considered a commit header and is used in various Git commands. For example, Git-format-patch (1) turns a commit into email; the command uses the commit header for the subject line and the rest of the text for the body of the letter.
First, not every commit requires filling in both the header and the body. Sometimes one line is enough, especially when the changes are so small that no additional information about them is required. For example:
Fix typo to user guide
This is enough; if the user wants to know what kind of typo was corrected, he can simply look at the changes themselves using git show or git diff , or git log -p .

If you commit something like this using the command line, it’s convenient to use the -m option for git commit :
$ git commit -m "Fix typo in user guide to user guide"

However, when a commit deserves some explanations and descriptions of the situation, you need to write them in the comment body. For example:
Derezz the master control program
MCP turned out to be evil and had become intent on world domination.
This is a commit throws
and turns it back into a chess game.

Comments that have a body are not so convenient to write with the -m option . It would be better to use a text editor for this. If you have not yet set up an editor for use with Git, read this section of the Pro Git book .

In any case, the separation of the title and comment body will pay off when viewing the log. Here is the complete commit record:
$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <kevin@flynnsarcade.com>
Date: Fri Jan 01 00:00:00 1982 -0200
 Derezz the master control program
 MCP turned out to be evil and had become intent on world domination.
 This is a commit throws
 and turns it back into a chess game.

But the git log --oneline command , which displays only the title bar:
$ git log --oneline
42e769 Derezz the master control program

Or git shortlog, which groups commits by author, again, for short, shows only the title:
$ git shortlog
Kevin Flynn (1):
      Derezz the master control program
Alan Bradley (1):
      Introduce security program "Tron"
Ed Dillinger (3):
      Rename chess program to "MCP"
      Modify chess program
      Upgrade chess program
Walter Gibbs (1):
      Introduce protoype chess program

There are many other situations where it is necessary to distinguish between the header and the body of the commit - and for this they must be separated by an empty line.

2. Limit the header to 50 characters.


Technically, it is possible to go beyond 50 characters, but not recommended. This length of the title guarantees its readability, and also makes the author think about the most concise and precise wording to describe what is happening.
Hint: if you find it difficult to summarize the results of work, it is possible that there are too many changes in one commit. Strive to make atomic commits (this is a topic for a separate post).

The GitHub interface fully supports these conventions. He will warn you if you go beyond the limit of 50 characters:


And cut off all headers longer than 72 characters, substituting the ellipsis:


So strive for 50 characters, but note that 72 is a strict limitation.

3. Write the title with a capital letter.


It's simple. Start all headers with a capital letter.

For example:

  • Accelerate to 88 miles per hour

Instead:
  • accelerate to 88 miles per hour


4. Do not put a period at the end of the title.


There is no need for it. In addition, each character in the account when we try to meet the 50.

For example:

  • Open the pod bay doors

Instead:
  • Open the pod bay doors.


5. Use the imperative in the title


The imperative mood literally means: a form of a verb expressing will (order, request or advice). A few examples:

  • Clean your room (tidy up the room)
  • Close the door (close the door)
  • Take out the trash

Each of the seven rules that you are currently reading about is written in the imperative mood (“Go to the next line in the body with 72 characters,” etc.).

This form may sound a little rough, and therefore is not so often used . per. ]. But it is perfect for a commit header. One of the reasons is the fact that Git himself uses the imperative when he creates commits on your behalf.
For example, when using git merge, the following message will be added by default:
Merge branch 'myfeature'

And when using git revert :
Revert "Add the thing with the stuff"
This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

Or when clicking on the “Merge” button in the GitHub pull-request interface:
Merge pull request # 123 from someuser / somebranch

So, when you write your own messages to a commit in the imperative, you follow the rules laid down in Git itself. For example:

  • Refactor subsystem X for readability
  • Update getting started documentation
  • Remove deprecated methods
  • Release version 1.0.0

This method may seem inconvenient at first. We are more used to using the indicative mood, which is more likely to report facts. Therefore, commit messages are often about as follows:

  • Fixed bug with y
  • Changing behavior of X

And sometimes the headers just describe the contents of the commit:

  • More fixes for broken stuff
  • Sweet new API methods

There is a simple rule that will allow you to avoid mistakes.

A well-formed commit header should complete the following sentence:

  • If applied, this commit will < commit header >

For example:

  • If you are a refractor subsystem X for readability
  • If applied, this commit will update
  • If applied, this commit will remove deprecated methods
  • If applied, this commit will release version 1.0.0

An applied the if, the this the commit will of The merge pull request # 123 from user / branch

Make sure that the verbs in the other, not imperative, inclinations here will not work:

  • If applied, this commit will fix bug with Y
  • If applied, this commit will changing behavior of X
  • An applied the if, the this will of the commit more fixes for broken stuff
  • An applied the if, the commit will of the this sweet new the API Methods

Remember: the use of the imperative is only important in the commit header. In the body of a commit it is optional.


6. Go to the next line in the body of 72 characters


Git itself does not automatically wrap lines. Editing the comment body, you must remember about the right border and put line breaks manually.

It is recommended to move to the next line with 72 characters so that Git can freely indent and still get a total of 80 characters.

A good text editor can help with this. It's pretty easy to set up, say, Vim, to wrap a 72-character line to write a message to a commit. However, it turned out that IDE is terribly poor in supporting smart line breaks for commit messages (although the latest versions of IntelliJ IDEA have finally become better in this part). ( approx. lane - perhaps at the moment everything is much better ).

7. In the body answer the questions "what" and "why", and not "how"


In this commit from the Bitcoin repository, an excellent explanation is given of what has changed and why:
commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date: Fri Aug 1 22:57:55 2014 +0200
   Simplify serialize.h's exception handling
   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.
   As exceptmask always included 'failbit', and setstate was always
   it was called immediately raise an bit
   exception. Get rid of those sets
   with direct exception throwing (which also removes some dead
   code).
   As a result, good ()
   only 2 calls, one of which is in tests)
   by! eof ().
   fail (), clear (n) and exceptions () are just never called. Delete
   them.

Look at the changes in the code and consider how much time the author has saved for present and future project participants by describing the context of the work done in the commentary. Otherwise, he probably would have been lost forever.

In most cases, you can omit the details of exactly how the changes were made. Usually, the code speaks for itself in this sense (and if it is so complex that explanations are required, then there are comments for it in it).

Focus primarily on explaining the reasons for which changes were made - describe the situation before making the change (and what was wrong with it), the situation after and why you chose this way of solving the problem.

Maybe in the future you will thank yourself for it!

Tips


Love the command line. Forget about IDE.


There are many reasons - by the number of Git commands - to use the command line to the maximum. Git is a hugely powerful tool; IDE - the same, but each in its own way. I use IntelliJ IDEA every day, I often dealt with others (for example, Eclipse), but I have never seen the integration of Git in the IDE with the simplicity and capabilities of the command line (once you understand it).

Certain IDE version control features are invaluable, for example, automatic execution of git rm when you delete a file, or other necessary git-pieces when you rename it. But it's much worse when you try to use the IDE to make a commit, merger, relocation ( rebase ) or a complex analysis of the history of commits.

When you want to unleash the full potential of Git, the command line is unmatched.
Remember that if you use Bash, Zsh or Powershell, there are command completion scripts that save you from the painful need to remember all the subcommands and options.

Read the Pro Git book


Gorgeous book Pro Git ( also in Russian - approx. Lane ) is freely available. Take advantage of this!

Also popular now: