A Note About Git Commit Messages
tbaggery.com
tbaggery.com
Does anyone have a good explanation of why commit messages should be in the present tense? (Beyond what the article says: "This convention matches up with commit messages generated by commands like git merge and git revert.") Why do commands like git merge and git revert generate commit messages in the present tense? The best explanation that I can think of is an analogy to literature: literary analysis is written in the present tense, because any time you open a book, the story is happening now, in the present tense. I don't quite buy that, but it's the best explanation I've come up with.
For example, think about the "fast-forwarding", "rewinding" and "replaying" that Git does. When you rebase, Git rewinds your divergent commits, fast-forwards the branch, and then replays your commits again. What happens when it replays those commits? Fix login bug. Update copyright year. Ignore log directory. Done!
I could understand if it were in this format: Fixes login bug. Updates copyright year. Ignores log directory. Those seem so much more like actions than the other.
Possible Explanation for present tense commit messages - Commit messages are treated as Instruction(s) to a third person, as if she is applying the patches one-by-one.
"Implement Feature A"
Now, "Fix the bug in the previously developed Feature A" etc.
That makes more sense (to me) for the example of rebasing - the applied diffs become a list of commands of what to do: Do this! Do that!
To disclose fully, I had only a notion of this before resorting to Wikipedia to confirm and provide some clarity. http://en.wikipedia.org/wiki/Grammatical_tense and http://en.wikipedia.org/wiki/Grammatical_mood
- "Fix bug" is simple present
- "Fixing bug" is present progressive
Other reasons to prefer it:
* It's generally shorter than the alternatives: "Implement" versus "Will implement", "implements", or "implemented".
* I think it's actually more accurate to say that commit messages should be in the imperative mood, not the present tense. The message is basically telling some unspecified agent to do something "Fix this bug." That lines up with the imperative form we use to write a lot of code.
Branches and commits can be merged and rebased left and right, and it only seems to follow that commits have an intrinsic state that's (not to be cliché) timeless. Patches and commits, regardless of when they're written, provide changes and accomplish X Y and Z -- it's only when one runs the code that time comes into play.
Semantics, I suppose, or I have had too much coffee this morning.
> On an 80 column terminal
> Good email netiquette dictates we wrap our plain text emails (for) an 80 column terminal.
I think format should be separated from presentation and presuming people should use a particular display device is wrong. These are well established principles and Unix, although lacking a tradition of interface design, isn't some kind of exception.
* I use a modern email program (I use gmail but this would include, say, mutt).
* I sometimes use a wider terminal. Sometimes I use a narrower one. On my system (OS X default 10.6) less handles this just fine unless some 72-character-neckbeard screws it up.
* I sometimes use a GUI tool to examine messages, like github. These may be wider or narrower.
In all these cases forced 72 character wrappings look terrible.
In the real world, however, lots of people use editors that don't have good soft-wrap support turned on by default, meaning that they're going to be doing hard-wrapping at some width. `git log` does not do any wrapping of messages, so depending on your pager settings you either get the line going off the edge of the screen or being wrapped by your terminal with no regard for word breaks.
Furthermore, even when soft-wrap is supported, it sometimes makes text harder to read; if your window is wide, and it just uses the whole thing displaying 150 characters per line, it can make the text a lot harder to read than a nice narrow column of text. I have this problem on the web a lot; some sites use multiple columns which take up lots of horizontal space (under the assumption that everyone runs their browser full-screen), which makes me widen my window, but then I come across a site that just uses the whole width for one big block of text, which now has unreadably long lines.
Given that many of the tools in question don't support soft-wrapping usably, standardizing on 72-column hard wrapping is a reasonable approach. Lines don't come out unreadably long that way, they will be displayed reasonably in `git log` and other tools on standard-width terminals, and they will display well in 80-column email clients even with several levels of quoting.
For example:
I guess it also depends on who your audience is. Most of the devs I've
worked with use modern software, so long lines have never been an
issue for me. I could see where some teams would have a culture of
using more basic tools that it would become more of an issue. Of
course, typography plays a role, too. I don't generally use a
monospace font for reading normal text, and proportional fonts seem
to work better with this outdated style.I'm sure this message was fine in their mail reader:
http://www.ietf.org/mail-archive/web/manet/current/msg11520.... (chosen only b/c I was reading through the list this morning)
But now I must horizontally scroll :(
> This is a short paragraph that I am quoting that
> someone
> else sent to me.No more scrolling.
From a web standpoint, the author of this email did the right thing: introduce very little formatting (only paragraph breaks) and leave it up to style sheets to render his text the way the reader wants it.
That's how you get the same text to render perfectly on a twenty column display (e.g. an old phone), a 30' inch monitor and everything in-between.
Introducing manual newlines at arbitrary points (e.g. 80 columns) is a bad practice that assumes that everyone will read your text on the same device.
Relevant explanation:
http://beust.com/weblog/2009/03/10/of-kindle-and-web-usabili...
> Exactly. That's why you write it to the lowest common denominator, so
> that everyone can use it well.
Reads great!Also, I probably would have moved the ', so' to the next line, so that it reads a bit better.
And people who have really large screens could use vertical splits or maybe tilling window managers to utilise their screen space more effectively.
It makes sense to write for the least common denominator.
(bare repo): # Make sure receive.denyDeleteCurrent = ignore
(Dev A): git push
(Dev B): git pull --rebase # you can make this the default for a particular tracking branch so it is just "git pull"
(Dev B): # do some work
(Dev B): git commit
(Dev A): git commit --amend
(Dev A): git push origin :master # Deletes remote master. Not required for shared branches -- those can simply be replaced -- but "master" is usually the "current branch" for a repo, so it bears knowing.
(Dev A): git push origin master:master # And now we replace the remote's version with our local version.
(Dev B): git pull --rebase # Updates pointers and applies the new commit on top.
Yes, if you do even more devastating history changes than this, Dev B needs to dig a little further on why his rebase is going haywire. THIS is why people fear the history change; it is sometimes extra work for downstream developers to handle the rearrangements (and we developers like to be lazy and for everything to work smoothly the first time). Thankfully, downstream developers can solve these problems with a few git tools, including "rebase --onto" and cherry-picking. But in the case of a quick and simple commit amend, all is well.
Alternatively, you can code review, but sometimes people are in a rush, and you run into this situation. In most environments, I wager it will be okay, especially if there is communication on the changes and reasonable education on version control theory.
There is a race when dev A deletes master though, right? What if someone else made a commit between when dev A last pulled and when dev A deletes master, wouldn't that commit be lost? In the process of testing this I managed to lose dev B's work a couple times, so I still think this kind of operation is too risky to be worthwhile.
In case anyone is interested I made a test script based on Xurinos's example: https://gist.github.com/769904
Yes and no. I could say that this is where communication can help a little, and it depends entirely on your local group's policies, but that would be the easy cop-out. Let's say it really happened.
Dev B's git pull --rebase will also lose the change; it was assumed to be pushed up, and a git fetch means that you are reflecting exactly what is in the remote branch. But changes are never truly lost+++. Dev B can check his reflog, find his original commit, and cherry-pick it in, resubmitting it. Afterwards, he can bonk Dev A over the head for not pulling before pushing.
There is a danger that Dev B would not notice, but from a little test I just did, he is going to get some nasty messages during his git pull --rebase that should indicate that something interesting just happened.
I have not looked into this, but does anyone know if it is possible to lock a remote git repo (aside from the automatic push lock)? If one could manually lock the repo, the process would be to lock, pull, push-delete, push-for-real, and unlock.
+++ depending on your git configuration policy. I think you have 30 days before dangling commits are truly pruned permanently.
Or maybe if Git could do a "test and set" on a ref? For example, instead of two step delete and recreate, how about "git push origin +master": forced update, but your Git sends "update master to 1234abcd iff your current master is 5678fedc" where 5678fedc is where origin/master points on your local Git. If someone had snuck in a new commit Git would then fail and you could deal with it. (Of course, on a busy shared repository "deal with it" could take a while if people keep sneaking in commits; but I suspect that kind of commit volume is very rare.)
Don't do this:
git push origin :master
Do this: git push -u --force origin master:master1. Use format-patch and review via email. 2. git push origin +HEAD:cr/js2
Now another developer can pull that branch and review it before it is merged to master.
3. Use Gerrit.
This is counter to a lot of the "commit often" mantra that so many git people have, but it's working better for me.
It has the added advantage of being able to merge commits that fix intermediate bugs that you introduced yourself and fixed immediately. There is no reason to bore other people with those.
Also, less has line wrapping and who develops using 80 character terminals anymore? Maybe the author has a time machine back to 1981? I want access to that!
Something that fits nicely in that space is helpful in that case.
"improve crapping"
(typo: should be cropping)