read

Note: This post refers to running git commands in a terminal running a bash shell… YMMV.

I love using git from the command line, I have SourceTree installed which is a fantastic GUI, but I’ve found that for me personally nothing beats the level of control and response that you get from manually performing Git operations. That said, something that often trips me up is when I start quoting terms in my commit messages, I land up breaking syntax…

1
2
3
$ git commit -m 'test commit 'hello world''
error: pathspec 'test commit hello' did not match any file(s) known to git.
error: pathspec 'world' did not match any file(s) known to git.

While its easy to spot that I’m doing something stupid in the above commit, its very easy to let an apostrophe slip into a longer and more natural commit message:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git commit -m 'Here is the summary of my commit
And a sentence or two where I describe it's background before I move on and create a bulletted list of change explanations...
error: pathspec 'Here is the summary of my commit
And a sentence or two where I describe its' did not match any file(s) known to git.
error: pathspec 'background' did not match any file(s) known to git.
error: pathspec 'before' did not match any file(s) known to git.
error: pathspec 'I' did not match any file(s) known to git.
error: pathspec 'move' did not match any file(s) known to git.
error: pathspec 'on' did not match any file(s) known to git.
error: pathspec 'and' did not match any file(s) known to git.
error: pathspec 'create' did not match any file(s) known to git.
error: pathspec 'a' did not match any file(s) known to git.
error: pathspec 'bulletted' did not match any file(s) known to git.
error: pathspec 'list' did not match any file(s) known to git.
error: pathspec 'of' did not match any file(s) known to git.
error: pathspec 'change' did not match any file(s) known to git.
error: pathspec 'explanations...' did not match any file(s) known to git.

Easy to do right? Just an apostrophe in it's is all it takes…

I used to hack around this, lazily and at the expense of my commit messages I would use a backtick instead of quotes, and frequently omit grammatical apostrophes. Yuck! I need to change that right?!

Immediately I have three options or habits to adopt to prevent me from falling into this trap again:

  1. Get off the command line and use a GUI
  2. Stop writing commit messages inline and use an editor in my shell
  3. Escape my quotes

Option 1: Use a GUI

As I alluded to earlier, this just doesn’t work for me, I admit from time to time I do, but since so much of what I do is driven from the terminal, it is my happy space and I’d rather not!

Option 2: Use an editor in terminal

I normally perform commits using the git alias git cm == git commit -m to save keystrokes… If I rather performed a git commit (without the -m modifier) that would open up vi editor and I could edit my message to my heart’s content before saving and exiting.

In all fairness, this is probably a good option, just a workflow I’m slightly less used to. It feels like more steps, more keypresses (to enter INSERT mode in vi, to do the old ESC, :wq sequence).

Yet, if I truly have to craft a message, I’d win from the extra editing power available. I should probably give this habit a 30 day trial :D

Option 3: Escape my Quotes

This is the screamingly obvious solution, but one that is less than intuitive to many, myself included.

Mixing Quotes

There is a false confidence solution, which is to mix your quotes… You can use doubles for the message and singles for anything you’re quoting inside the message, but this fails quickly when you use the dollar sign, since the terminal will expect that this is a variable:

ie.

1
git cm "This works Mr O'Gregor"

whereas:

1
2
3
4
$ git cm "This won't because of the dollar sign in scope.$apply the apply part will be interpreted as a variable - and omitted!"
[master fcce7f3] This won't because of the dollar sign in scope. the apply part will be interpreted as a variable - and omitted!
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 myfile.txt

And thats where it gets dangerous. Given how often I refer to $ prefixed terms in my messages, this is likely to catch me out and since it does actually perform the commit I may not even notice!

Yes, I can escape the $, as in git cm "\$moneydollars" but there is a big chance I may not remember to.

Using Single Quotes

The terminal interpolation of variables makes double quotes dangerous and fortunately using single quotes around the commit message prevents this.

1
2
3
4
$ git cm 'this will not interpolate: $example'
[master 7580885] this will not interpolate: $example
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 myfile.txt

Great stuff, no PEBKAC error happening, so this is a much better habit to get into, but what about apostrophes?

I’ll still need to escape them but this won’t cut the mustard:

1
git cm 'It\'s... not going to work'

While simply escaping the offending character is inuitive to most C style coders, thats simply not how the terminal parses the statement.

It will believe my statement is ongoing and the terminal will offer me a continuation prompt >.

What will work is if I escape it correctly for the terminal like this:

1
git cm 'It'\''s... going to work this time!'

Seemingly bizarre to the uninitiated, but try this out in your terminal:

1
2
$ echo 'hello'
hello

As expected, but now try this:

1
2
$ echo 'he'll'o'
hello

The terminal is parsing the string from the first apostrophe… When it finds the next it will look for another apostrophe and concatentate the contents, then it will resume parsing and concatenating until it finds the last apostrophe at which point it stops string parsing.

An in depth explanation of this can be found in this SO answer by liori and this one by Adrian Pronk.

Phew! and there we were thinking this would be simple

Conclusion

Given how easy it is to mess things up with inline commit messages (using the -m switch) I think it is definitely worth committing using a shell editor (like vi/vim) a try.

If you do want to use inline commit messages, be wary of the issues and my recommendations are:

  • Use single quote message delimiters to avoid potentially losing parts of your commit messages identified as variables unknowingly.
  • Escape apostrophes in the message using '\''

Please hit me up on the comments if you have a better way, I’ll be very keen to hear it!

Blog Logo

Stephen James

JavaScript and Front-End Developer


Published

Proudly published with Hexo
Image

Stephen James' Code Blog

Back to Overview