How to Write a Git Commit Message (2014)(chris.beams.io) |
How to Write a Git Commit Message (2014)(chris.beams.io) |
I'd also say: remove thw -m option from git and force people to open the editor. Do not accept messages shorter than 3 lines, start the editor with a template
Title
What changed and why it changed.I commit very often and usually small, "atomic" changes most of the time.
What I will do, is that I start the commit message with the most important sentence and add less important sentences after, so even if it exceeds 80 chars and you can't see the whole message you will still get the most relevant info without having to scroll sideways.
For reference, here are the commits to a project I am currently working on: https://github.com/eriknstr/jumper/commits/master
here's
some
code.
Concentrating on form over substance is myopic.>Git can take the commit message from a file using the -F or --file flags:
>git commit -F message.txt
So something like
echo 'pmontra\n say\n this\n should be several lines' | git commit -F /dev/stdin
would get around your block.echo is a very non-portable command. POSIX says: "if any of the operands contain a <backslash> character, the results are implementation‐defined."
We agree on a short list of leading active verbs:
Add = Create a capability e.g. feature, test, dependency.
Cut = Remove a capability e.g. feature, test, dependency.
Fix = Fix an issue e.g. bug, typo, accident, misstatement.
Bump = Increase the version of something e.g. dependency.
Make = Change the build process, or tooling, or infra.
Start = Begin doing something; e.g. create a feature flag.
Stop = End doing something; e.g. remove a feature flag.
Refactor = A code change that MUST be just a refactoring.
Reformat = Refactor of formatting, e.g. omit whitespace.
Optimize = Refactor of performance, e.g. speed up code.
Document = Refactor of documentation, e.g. help files.
I'm wondering if the same general idea is applicable to other types of commits given your list. For example, if you are regularly adding features and a certain part of the code base is touched, perhaps with a lower ratio of "refactor" commits, that code could be a solid candidate for refactoring.
Here's the tool i mentioned anyway https://google-engtools.blogspot.co.uk/2011/12/bug-predictio...
Start = Begin doing something; e.g. create a feature flag.
Stop = End doing something; e.g. remove a feature flag.
Could someone explain these and give a few examples?
The idea is that instead of making a version control branch to change feature A to feature B and then merging back into the mainline of development, you build an abstraction over the thing you want to change, build a new implementation of that abstraction, switch out the two and then (if you like) remove the abstraction, all within the main line of development.
So instead of history that looks like this:
* Merge branch 'feature-cookie-login' into master
|\
| * Polish up cookie feature
| |
. * Switch from tokens to cookies
. |
. * Clean up and refactor login code
|/
.
.
.
Your history looks like this: * Stop abstracting the authentication type.
|
* Switch from auth tokens to session cookies
|
* Add a SessionCookie authentication type.
|
* Start abstracting the authentication tokens as a generic authentication type
|
.
.
.
But with any completely arbitrary commits interspersed between those commits, as none of them break other code. The first one creates an interface, the second one reimplements the interface, the third switches the used implementation and the optional fourth removes the abstraction and deletes the old implementation.Using feature flags can increase a team's productivity by encouraging multiple commits a day, every day. It can also make rollbacks faster.
Instead of 'JAT-1241: app/index.js(opt): Optimised the index', 'Optimised the index' should be fine. Tools can understand that, and can already work out which files changed.
Some of the active verbs are also commands that automatically close/reference issues right out of the box on GitHub & BitBucket (& I'm sure on GitLab too)
Might try and get my team into using this.
At the moment our teams commit messages are a mangled mess of everyone's own 'commit language'. It can be really tricky to quickly scan over commit logs and get a feel of where development has been heading over the last x weeks.
The discussion that needs to happen before this is to understand what tools you want to make available to your developers in the future. Using git's history as a first class debugging tool is powerful, but it's by no means mandatory to provide. There's also a real cost to providing each of the tools.
- Do you want bisect to be available? Well, then you should have most commits represent a fully-functional version of the software. Consider squashing branches when you merge them.
- Do you want narrative documentation around strange choices? Fine-grained commits are a great place to put those thoughts, but they may discourage devs from writing those thoughts in inline comments.
- Do you want ownership via git blame? Line-by-line changes may help you identify who wrote the code, but that might prevent your developers from ever fully transferring ownership, which could create bottlenecks in startups that have a few long-tenure devs and a lot of recently hired devs.
I really like to think of git history as a context tool, like monitoring or unit testing or documentation. It's worthwhile to sit down with your team, define what you want them to be able to do with commit history, and build your commit style from there.
With git, it became very common to structure changes to a code base in many, very small commits. Rename a variable? Commit. Write some docs? Commit. Of course, the overall changes when developing a feature did not become smaller, they are now just distributed over many more commits. So I'd argue that a SVN commit was often conceptionally closer to what we now have with a git pull-request.
Why does this matter? Because It is kind of hard and not helping anyone if you describe your renaming of a local variable with an extensive docstring.
What I do miss however, is a good description of the overall change. I.e. now often the description in the merge commit is just the autogenerated message, but this is where I would like people to really take the time and describe the change extensively. This is why I like `--squash` merges, because they let people focus on the relevant parts in their description. I know, rewriting history is bad, but overall, I favour reading a history book than 18th century newspapers.
[X] not saying that there weren't small one-line-change commits, but overall they were rarer.
type(scope) message
e.g.
feat(button) added play button
Types are:
- feat: A new feature
- fix: A bug fix
- docs: Documentation only changes
- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- refactor: A code change that neither fixes a bug nor adds a feature
- perf: A code change that improves performance
- test: Adding missing or correcting existing tests
- chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
We use Add, Fix, Refactor, Reformat, Optimize, etc.
See my comment on this thread or https://github.com/joelparkerhenderson/git_commit_message
However, in the linked article no visual separation between type and message (and no scope) is something I consider less useful.
In the beginning the definition of "scope" is a bit wonky per project. However, once it solidifies you can easily start going through your log looking for "feat(endpoint)" to find new routes that have been added to an API for example.
One thing I noticed is that it's increased my confidence in my commits; at the moment that I go to write the commit message because I'm describing why I made the decisions I did it breaks logical inconsistencies between what I've actually done and what I think I've done. If I'm able to explain all the change I'm much more confident that it's correct.
Another is that bad commit messages have trained people not to read them. Often people will ask why I've made a change and then discover that the commit message contains the answer to their question!
> Wrap the body at 72 characters
Why? Because the git CLI doesn't wrap properly? To borrow a quote, that seems like a 'you' problem, not a me problem.
Maybe I'm just biased because these days I almost entirely interact with git through a GUI (either desktop client or web interface), and though I use the CLI occasionally (mostly for branch management, sometimes for quick commits) I can't think of the last time I used it for any type of history viewing -- pretty much any GUI is going to do a better job of that.
My team often uses markdown (mainly bulleted lists) and the output looks terrible when you insert manual line breaks (because markdown interprets that as meaning that you explicitly want a line break there) and you're viewing it on a screen/viewport that is either larger or smaller than 72 characters wide.
Unless you're explicitly using a publishing format (eg, LaTeX, PDF, postscript), the function of wrapping text should be a concern of the rendering of the output, not the origin.
Am I missing something here? Is there any other reason to manually wrap text besides the git CLI's handling of it as a viewer?
https://github.com/torvalds/subsurface-for-dirk/blob/0f58510...
I always send this to people as I teach them git.
1. Any article on structured git commit messages should mention git commit templates! https://robots.thoughtbot.com/better-commit-messages-with-a-...
I use a commit template for structure, as well as reducing boilerplate for expressive messages. Here is my default template on ibgib: https://github.com/ibgib/ibgib/blob/master/git-commit-templa...
2. I also use emoji (with a key there in the git commit template for reference) to communicate concepts like implemented, bug fix, etc., in a single emoji character. Note though that it is inappropriate when you start to do a pull request, as not all git message viewers will display the emoji. But I find it very useful FTMP.
3. Bullets are a simple way to enable both terse and structured comments within a commit.
Goals imposed by git: Commit subject < 65 "chars", commit message lines < 70 "chars".
All in service of the punch card god Hollerithus.
I can tell you that I have been programming for a very long time. So if someone asks me "Why does it MATTER if lines are longer than 80 characters?" then I can answer "Because it means that the distribution of line-lengths will be more uniform, meaning that you will be able to fit more code on the screen, meaning that the amount of scrolling you'll have to do when trying to understand the code is greatly reduced." And scrolling interrupts your focus, which is bad. But if I ask someone, "Why does it MATTER if verbs are in present or imperative tense?" no one can answer.
If you use a code management tool like BitBucket or GitHub, it seems like the unit of work is less a commit and more a PR. A PR's description can always be edited and refined for future engineers, and a PR (almost) always represents a block of work that can be reverted. Instead of creating a hundred different approaches to writing commits that engineers essentially have to get right the first time, why not just focus on documentation in the form of PR's? It seems like if you could trivially tie a commit back to the PR and ticket it came from, most of these problems would be solved.
So unlike PR's, if your coworkers criticize your commit messages it's already too late.
Are there any tools that allow you to initiate a commit as an 'intention stack' for work I am about to do, rather than work I have already done?
I'd love to be able to write an intent message "refactor XYZ.." before starting in on that activity, then when I have to go down another rabbit hole in the middle I push another intent message to the stack, then pop back out afterward and continue with XYZ. The final overall commit message could be auto generated from the initial intention and all tangents.
If there are more commits for the same task, all of them bare the same commit message. After each review, we add a comment to project management tool. That way we focus only on newer commits when performing another round of reviews.
Every other attempt to describe changes and intentions in one line seems doomed to me.
A commit should be a unit of work. Tests should pass before and after. The commit message should describe the change. Ensuring that you have a good commit message then influences what content you contain in a commit.
For example:
Problem: Windows build script requires edit of VS version
Solution: Use CMD.EXE environment variable to extract
DevStudio version number and build using it.
I got the idea from ZeroMQ's/hintjens' various repos. [ISSUE-ID]: Title
[Problem]
State problem and customer impact
[Solution]
Describe and justify solution
[Test]
Describe automated/manual testing- Test plan when there's no unit test (describes how to test that the patch actually works).
- Task ID (link to whatever is used to track tasks/bugs, as there's usually more context there).
- Blame rev when a patch fixes a bug, it's useful to know which commit introduced the bug.
Opens the pod bay doors
Instead of
Open the pod bay doors
?
You can read them in your head like this "Applying this commit will $MSG"
It even includes an example of not including a full stop - I'm all for examples, but sometimes they are not necessary.
Do other people not have actual work to do ?
I can't believe people whine about ways I spend my time (or what I choose to write about). It's not like you are being forced to read any of it.
GIT commit message are hardly significant, unless you are doing some form of automated release notes - and then you just follow whatever convention is required.
I've found that for smaller commits, if you have something long you want to explain in the commit message body... you should probably put it in a code comment!
If you don't think it merits a code comment, it's probably not important enough for people to look up the commit message body either (if only because the commit message body is less likely to be seen).
https://github.com/ribasushi/dbix-class/commit/1cf609901
Something like that I take it? :)
But I do not see a problem with rewriting history on a branch, if (and only if) you kind of know that no one else is pulling the changes. Or, when merging a PR, a rewrite is okay too, if the next feature will be branched off of the trunk, too.
Also, mercurial's tooling seems to help https://www.mercurial-scm.org/wiki/ChangesetEvolution with rewritten history by making it easier to track history rewrites. Basically I think this is a path in version control systems worth exploring.
Has it really become so common with git? I don't see such trend around me.
I'm replying to you but this is directed at everybody who advocates squash merge and discourages small commits.
IMO this is a tooling problem, plain and simple. When I am committing to Git, I am using the "write" components of Git which are incredibly powerful. I can commit in as small a chunk as I want and preserve the richest history of all the small changes I've made, knowing full well that the state of the code at HEAD will not be degraded for doing so. If I make two small independent changes, I can feel free to branch them separately and then merge them together to show that they could have been performed in any order.
When you read my history, you are using the "read" components of Git. Unfortunately these are not as powerful. You can do some nice things, like if you want to treat history as a straight line you can use `git log --first-parent` and you'll see only the merge commits (as if all merges had been squash-rebases).
It would be much better if you were able to collapse or expand any sequence of linear commits to gloss over the lower level details. But as far as I'm concerned, this is a problem with the "read" components of Git, not the "write" components, and so I will continue to use the "write" components to their full power. And the best part is that if I do it this way, we can improve the "read" components and allow the reader to collapse my verbose history, but we will never be able to expand pre-collapsed history.
I find the PR mechanism works great for the view of the whole, whereas the individual commits are great for the pieces. So in my commit history, you can read the timeline, and then if you want to see the commits squashed down, you click on the individual PR. On the PR screen (assuming you're using GitHub), it has a nice list of the subject lines of each of the individual commits.
The more I think about it, the stranger a strong aversion to rewriting commit history for clarity is. In university if I did some math / physics calculation, I would often start, and once I got somewhere, make a clean copy of the successful work to have a concise and revised version.
This was often the source of merge hell. Half of what makes git merges easier is the smaller commits that it encourages.
The relevant quote from the link:
Some things should not be word-wrapped. They may be some kind of
quoted text - long compiler error messages, oops reports, whatever.
Things that have a certain specific format.
The tool displaying the thing can't know. The person writing the
commit message can. End result: you'd better do word-wrapping at
commit time, because that's the only time you know the difference.
[0] https://github.com/torvalds/linux/pull/17#issuecomment-56611...EDIT: small clarification and formatting
If the tool applied reasonable wrapping heuristics and got it wrong once in a while, it could easily offer a `--no-wrap` option to let users see the message exactly as it was composed.
Generally, in markdown, if you insert a line break, it won't translate to an explicit line break unless you put two in a row, or if there is 2+ spaces at the end of the line.
See [1] for an illustration
[1](https://johnmacfarlane.net/babelmark2/?text=This+line%0Ashou...)
First off, the commit message is plain text (by design) and can't be "wrapped" automatically, and any tool that tried would be insane.
The reason for 72 characters is that the CLI, like lots of other presentation mechanisms (including quoting in other commits or in code), wants to indent your message for readability. And the uniform standard width for terminals has been 80 characters for like four decades now.
Must it be? I dunno. I can imagine a uniform agreement among a broad team that everyone will assume a 100 character line and all tools should enforce that. Maybe a little more, but not that much because even on a modern screen you want to have two full terminals of text readable at a time.
But that's just a number. You'd still be told by your commit message style guide (or checkpatch.pl, or whatever) to wrap your lines manually at 92 characters. Is 25% more bytes on a line really worth yelling about?
This text box I'm replying to you with is a plain text textbox. It word-wraps just fine.
There's myriads of plain text inputs and outputs you encounter every day and they all word wrap just fine.
The terminal is an aberration in that regard.
But note the comment above mentioned a commit for variable change. Or a commit for adding some comment sentence. Nano commits they are.
Sure, tasks should be small, easy to get, easy to review. But there must be a balance. Going to extreme, both ways, doesn't do any good.
Uhh, there's plenty of difference between your local repository and the remote one. One is local and used just by you and one is remote and used by many, for starters. Changes aren't automatically synced between them. You can rewrite commits locally to your heart's content (which I do all the time). You aren't "locked in" to anything until you've pushed it to a shared repository and someone syncs from it.
By the time somebody else criticizes your commit messages, you've already pushed. It's too late. All that time you had while the commit was local-only means nothing, unless you brought your coworkers over to your computer to review your commits before creating a PR. Expecting developers to get commits right the first time (before pushing) is not a sustainable solution.
No it doesn't. In fact I had to edit a comment I made above this one about four times until I got the formatting right. It annoyingly ignored me doing this:
line one
line two
line three
and assumed I meant this: line one line two line threeMy original point is that plenty of software does plaintext wrapping just fine and it's pretty ridiculous that consoles are stuck in this 80 character mindset.