383

Git treats lines starting with # (hash, number sign, octothorpe, pound sign) as comment lines when committing. This is very annoying when working with a ticket tracking system, and trying to write the ticket number at the beginning of the line, e.g.

#123 salt hashed passwords

Git will simply remove the line from the commit message. Is there a way to escape the hash? I tried \ and !, but nothing works. White space before # is preserved, so that's not a working solution to the problem either.

knittl
  • 246,190
  • 53
  • 318
  • 364
  • Why not adopt a convention like Bug#123? – Alex Budovski May 07 '10 at 11:23
  • 10
    @AlexBudovski because there's value in brevity. – Xavi Mar 19 '14 at 04:16
  • 11
    Since git 1.8.2 (February 2013), `git config core.commentchar` allows to configure that comment character. See [my answer below](http://stackoverflow.com/a/14931661/6309) – VonC Mar 27 '14 at 13:14
  • 5
    Since Git v2.0.0 (2014.05.21) `git commit --cleanup=scissors` will be more flexible. See detail in [my answer](http://stackoverflow.com/a/37058066/603949) – Sungam May 09 '16 at 17:41
  • 5
    I must say, I'm surprised the GitHub people didn't think about this problem when they decided to mark issue numbers with hashes! – Michael Scheper Aug 31 '16 at 19:20
  • `git config core.commentChar "@"` solved it for me. I rarely want to add E-Mails to git commits – Martin Thoma Jan 15 '18 at 11:34
  • 2
    @Michael To be fair, this convention was already used by Mantis, Trac, Redmine and probably others. I suppose that GitHub just decided to follow it instead of reinventing the wheel. See https://stackoverflow.com/questions/40495/bug-tracker-setup-with-git-integration – kelvin Aug 05 '18 at 21:52
  • 1
    Came here because I'm writing a commit message about a #define in C, and #define happens to be at the start of the line. I could futz about with the exact wording to make it not at the start of the line, or put in a space before the #, or some other workaround. Looks like I'll be using `--cleanup-=scissors` from now on. – studog Sep 11 '19 at 14:55
  • Note that this has nothing to do with GitHub and everything to do with Git, which lies at the core of GitHub. And also, what @kelvin said. – fourpastmidnight Jun 01 '23 at 18:00

10 Answers10

305

This behaviour is part of git commit's default 'clean-up' behaviour. If you want to keep lines starting with # you can use an alternative clean-up mode.

E.g.

git commit --cleanup=whitespace

If you do this you have to be careful to remove all # lines that you don't want to appear in the commit.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 3
    The next question is: Where can I edit the commit message comments that git introduces which start by default with a # ? – Alex Apr 16 '12 at 14:51
  • 4
    @Alex: It's controlled by the `commit.template` git configuration variable. – CB Bailey Apr 16 '12 at 14:57
  • 35
    This works great for amending existing commits also. Eg: `git commit --amend --cleanup=whitespace` – James Andres May 02 '12 at 14:40
  • @CharlesBailey: I was expecting to get rid of the predefined text with git commit -t /dev/null but it is still showing that – Alex Oct 01 '12 at 12:59
  • As you are able to have a commit message of "#123 Commit message" as well as comments in clients such as GitHub for Mac and SourceTree I guess is what these clients are doing yes? – Phil Ostler Feb 12 '14 at 11:47
  • Then be careful during `git rebase --interactive` and using any commit message editing stanza (like reword or squash) – Julien Sep 08 '15 at 08:43
  • @JamesAndres, at least in git 1.7.1 (default on RHEL 6), `git commit --amend --cleanup=whitespace` does not preserve or restore any comment lines previously stripped out by git's cleanup mechanism. Not sure what output you are looking at (I thought maybe it worked the way conflicts during cherry pick preserve the commit message for afterwards) but you will still have to get your `#desired lines` back through some other means or recreate them. – Wildcard Sep 21 '17 at 01:07
  • 2
    `--cleanup=verbatim` is also useful – Petr Felzmann May 10 '18 at 09:46
  • 1
    Since this is 2020, everyone just wants [`--cleanup=scissors` and `[commit] cleanup = scissors`](https://stackoverflow.com/a/37058066/2809027) instead. Those do everything `--cleanup=whitespace` does as well as automatically stripping the commented changeset suffixing every commit message. – Cecil Curry Jun 05 '20 at 06:55
168

Note that, since git1.8.2 (February 2013), you can use a different character than '#' for the commented line in the commit message.

That allows you to use '#' for your bug number reference.

Various "hint" lines Git gives when it asks the user to edit messages in the editor are commented out with '#' by default.

The core.commentChar configuration variable can be used to customize this '#' to a different character.


In theory, you could put a core.commentChar word (multiple characters), but git 2.0.x/2.1 will be stricter (Q3 2014).

See commit 50b54fd by Nguyễn Thái Ngọc Duy (pclouds):

config: be strict on core.commentChar

We don't support comment strings (at least not yet). And multi-byte character encoding could also be misinterpreted.

The test with two commas is updated because it violates this. It's added with the patch that introduces core.commentChar in eff80a9 (Allow custom "comment char" - 2013-01-16). It's not clear to me why that behavior is wanted.


git 2.0.x/2.1 (Q3 2014) will add an automatic selection for core.commentChar:
See commit 84c9dc2

When core.commentChar is "auto", the comment char starts with '#' as in default but if it's already in the prepared message, find another char in a small subset. This should stop surprises because git strips some lines unexpectedly.

Note that git is not smart enough to recognize '#' as the comment char in custom templates and convert it if the final comment char is different.
It thinks '#' lines in custom templates as part of the commit message. So don't use this with custom templates.

The list of candidate characters for "auto" are:

# ; @ ! $ % ^ & | :

That means a command like git commit -m '#1 fixed issue' will automatically switch the commentChar to ';', because '#' was used in the commit message.


See "Making a hash of things – using #s in Git commit messages" by Tom Wright

The Stackoverflow answer I linked to above also mentions a feature in Git that will choose a comment character automatically, based on the characters you use in commit messages.

git config --global core.commentChar auto

Sounds great right?
Unfortunately, it only changes the comment character based on commits made after you turn it on; it doesn’t use your commit history to inform the choice.

To my mind, this is a great feature hobbled by poor execution.
It seems like a feature that would be effective only if it were on by default:

  • One group of people will simply avoid using hashes in commits because they are familiar with the consequences.
  • Others (like us) will only realise they need to change the comment character when they need to do a rebase. It doesn’t make sense in this situation to add a new commit just to trigger the desired behaviour.
  • A third group of people will consciously accept early on that they need to change the default comment character and will simply choose an alternative.

In other words, having this feature available as a non-default option helps virtually no-one.
Since having it on by default would do nothing to harm any users, and would remove a pain point for some users, I can’t work out why this isn’t the case.
Git isn’t famed for its usability, but to have a fix available and not to turn it on seems gratuitously user-hostile.


Note: Git 2.41 (Q2 2023) adds:

See commit d3b3419 (27 Mar 2023) by Kristoffer Haugsbakk (LemmingAvalanche).
(Merged by Junio C Hamano -- gitster -- in commit 5c93cfd, 31 Mar 2023)

config: tell the user that we expect an ASCII character

Signed-off-by: Kristoffer Haugsbakk

Commit 50b54fd ("config: be strict on core.commentChar", 2014-05-17, Git v2.1.0-rc0 -- merge listed in batch #2) notes that “multi-byte character encoding could also be misinterpreted”, and indeed a multi-byte codepoint (non-ASCII) is not accepted as a valid core.commentChar.

The message is now:

core.commentChar should only be one ASCII character
                                    ^^^^^
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    To fix syntax HL after this, see this related question: http://stackoverflow.com/questions/16164624/edit-vim-syntax-highlighting-for-git-commit-messages – Alois Mahdal Apr 23 '13 at 10:02
  • @Guten True, I have reworded the answer to reflect that. – VonC Jan 30 '14 at 06:44
  • Doesn't seem to be supported during interactive rebase. – newbyca Jul 13 '14 at 23:29
  • 1
    @newbyca with what version of git do you see that not supported during an interactive rebase? – VonC Jul 14 '14 at 06:33
  • @VonC thanks for keeping me honest :) ...I was using msysgit 1.8.1. Just upgraded to 1.9.4 and rebase -i honors core.commentchar now. Thanks again! – newbyca Jul 19 '14 at 22:28
  • 3
    So, to set this you can do, e.g: `$ git config --global core.commentchar ';'` – davetapley Sep 30 '14 at 20:23
  • 9
    I love this answer. Oneliner for the new suggested solution: `git config --global core.commentChar auto` – aross Mar 12 '18 at 16:08
  • 3
    Why on earth isn't "auto" the default? Thanks for your answer. – Rich Jul 10 '19 at 15:39
  • A nice [blog post from Tom, 2018](https://blog.tdwright.co.uk/2018/09/15/making-a-hash-of-things-using-s-in-git-commit-messages/) which redirects back to this SO answer :-) I found the post 1st, then the SO entry here. In the post there are a bit more details about `auto` – KargWare Jan 12 '23 at 16:38
  • @KargWare Thank you for your feedback. I have included a reference to that post in the answer for more visibility. – VonC Jan 12 '23 at 17:14
128

Answers here are good and detailed, but for a git noob like me customizing git config options isn't so obvious. Here is an example to change from # to ; for comment characters:

git config core.commentChar ";"

That's all you need to do.

Slipp D. Thompson
  • 33,165
  • 3
  • 43
  • 43
Matthieu Napoli
  • 48,448
  • 45
  • 173
  • 261
  • 8
    This *also* changes the default commented text that git adds to a commit message when one uses `git commit` to open up the configured editor to edit a commit message ! – Michahell May 01 '17 at 14:51
  • 12
    For one-off fixes, use this: `git -c core.commentChar="|" commit --amend` (replace `|` with whatever you want). – yurisich Mar 20 '20 at 12:01
64

You can use the command line option -m:

git commit -m "#123 fixed"
Olivier Verdier
  • 46,998
  • 29
  • 98
  • 90
63

If you're doing an interactive rebase, then when you save your commit message with nothing in it (because the # at the beginning has made it a comment and therefore it's been ignored) git will show you what to do:

Aborting commit due to empty commit message.
Could not amend commit after successfully picking 5e9159d9ce3a5c3c87a4fb7932fda4e53c7891db... 123 salt hashed passwords
This is most likely due to an empty commit message, or the pre-commit hook
failed. If the pre-commit hook failed, you may need to resolve the issue before
you are able to reword the commit.
You can amend the commit now, with

        git commit --amend

Once you are satisfied with your changes, run

        git rebase --continue

So, just amend the message:

git commit --amend -m "#123 salt hashed passwords"

and continue the rebase:

git rebase --continue
Owain Williams
  • 2,387
  • 17
  • 22
46

git commit --cleanup=scissors should be used. It's added to Git v2.0.0 on 2014.05.21

from git commit --help

--cleanup=<mode>
  scissors
    Same as whitespace, except that everything from (and including) the line
    "# ------------------------ >8 ------------------------" is truncated if the message
    is to be edited. "#" can be customized with core.commentChar.
Slipp D. Thompson
  • 33,165
  • 3
  • 43
  • 43
Sungam
  • 1,684
  • 1
  • 21
  • 24
  • 1
    I don't understand how this is any better than using `commit.cleanup = whitespace` and removing `# …` commentary by-hand, as @CharlesBailey has already suggested.  `scissors`-mode just additionally cleans up the scissors-syntax used by `git` `format-patch`/`mailinfo`/`am`; _it does **not** use the `…-- >8 --…` syntax when adding commentary to commit messages_. – Slipp D. Thompson Jan 24 '17 at 02:01
  • 1
    1. I think it's better because I don't need to "removing `# ...` commentary by-hard. 2. I'm not so sure about the second part of your comment, the `scissors` mode is definitely in the `git commit --help`. What version of `git` are you using? @SlippD.Thompson – Sungam Jan 24 '17 at 18:01
  • Huh? `whitespace` mode offers stripping of 1. leading and trailing empty lines, 2. trailing whitespace, 3. collapse consecutive empty lines. `scissors` offers stripping of 1. leading and trailing empty lines, 2. trailing whitespace, 3. collapse consecutive empty lines, 4. everything from (and including) the line `# -…- >8 -…-`. However, scissors lines (`# -…- >8 -…-`) are only inserted when using `git-format-patch`/`mailinfo`/`am`. Therefore for a normal `git-commit`/`merge`/`rebase`/`cherry-pick` workflow, `scissors` stripping mode offers zero benefits over `whitespace` mode. v2.11.0 – Slipp D. Thompson Jan 25 '17 at 04:13
  • @SlippD.Thompson What version of git are you using? I'm using 2.8.3 and `git commit --cleanup=scissors` *DOES* prepend the `# ------------------------ >8 ------------------------` line before the `git status` info. Like below: ` # ------------------------ >8 ------------------------ # Do not touch the line above. # Everything below will be removed. # On branch master # # Initial commit # # Changes to be committed: # new file: .gitignore ` – Sungam Jan 25 '17 at 17:46
  • _“What version of git are you using?”_ I already answered that question for you.  |  _“git commit --cleanup=scissors DOES prepend the # ------------------------ >8 ------------------------ line”_ It doesn't for me: http://imgur.com/a/GiB2j  |  Either older versions of git had this behavior and it's now been removed, or you have another config setting besides `commit.cleanup = scissors` that's doing this for you. _P.S. I tried with both `commit.cleanup` in `.gitconfig` and `git commit --cleanup=scissors`; no dice._ – Slipp D. Thompson Jan 29 '17 at 02:07
  • 2
    I believe I've gotten to the bottom of this.  Git does indeed insert the `# ------------------------ >8 ------------------------` before the status txt “It looks like you may be …”_ when using `scissors`; however, it inserts the scissors line _after_ the `# Conflicts: …` text.  I had `commit.status = false` set in my `.gitconfig`, so I wasn't seeing any status text, only the conflicts text.  I stand corrected; changing to upvote. – Slipp D. Thompson Jan 29 '17 at 03:04
  • Permanently enable this by adding `[commit] cleanup = scissors` to `~/.gitconfig` and your keyboard-weary fingers will thank you by not screeching in pain. – Cecil Curry Jun 05 '20 at 07:02
8

It just suffices to start the commit message with a space char just before the # char.

Then git stops regarding the line as a comment and github can use the hashed ticket number without any problems.

vim's default syntax highlighting even suggests the feature by changing the color from commentish to contentish.

enter image description here

helvete
  • 2,455
  • 13
  • 33
  • 37
  • 4
    But will the leading space be included in the commit message or will it be stripped? I'd rather not have commit messages start with an invisible character. That will lead to problems down the road – knittl Apr 26 '21 at 18:24
  • @knittl: The leading space will not get stripped. That's the whole purpose - otherwise the line would be treated as a comment. Can you elaborate on what problems this practice can lead to? I haven't encountered any so far. – helvete Apr 27 '21 at 09:04
  • 2
    Several problems and issues I can think of: 1) It is inconsistently indented 2) (Too) Simple scripts to extract the ticket number might fail on the leading whitespace 3) Why store one extra space character with every single commit message? 4) Too easy to forget [5) and finally: it does not actually start the commit message with the hash character, but a space ;)] – knittl Apr 27 '21 at 09:45
  • 2
    @knittl: Well yeah, you cannot both have the cake and eat it. I mentioned this approach because it is IMO by far the simplest while allowing both to start the message with a hash (not counting whitespaces) and to preserve the feature of hash-based commenting. Only the 2nd point is a sort of problem, but more of a hypothetical one IMHO. Thanks for the discourse anyway;-) – helvete Apr 27 '21 at 12:39
1

All my commits starts with #issueNumber so I put this boilerplate to my vim .git/hooks/commit-msg:

NAME=$(git branch | grep '*' | sed 's/* //') 
echo "$NAME"' '$(cat "$1") > "$1"

So let's suppose we have branch #15 and we make commit message add new awesome feature. With this approach final commit message will be #15 add new awesome feature.

valignatev
  • 6,020
  • 8
  • 37
  • 61
0

Use a different prefix for the ticket number. Or prepend a word to the ticket number, like "Bug #42". Or prepend a single space character to the line; if you wish to remove that whitespace you can add a commit-hook for that.

I personally would rather not have this sort of commit message manipulation done by a hook because it can be very irritating when it triggers when you don't want it to. The easiest solution is probably to re-think the problem.

wilhelmtell
  • 57,473
  • 20
  • 96
  • 131
  • 2
    different wording is only a workaround for the problem. if project guidelines state that a commit message must begin with the ticket id, then it will not work. and a post-commit hook is very ugly. i think i should report this "bug" to the git developers – knittl May 07 '10 at 11:39
  • 1
    Don't bother, that'd be wrong. Don't ask the git developers to work according to your guidelines. You wouldn't ask Dennis Ritchie to change the C language so it supports you variable names convention of starting with a hash character, right? The same applies here. If commit messages allow comments then this adds support for interesting things, like opening the commit editor with the diff added and commented out so you don't need to remember your exact changes. What's wrong with preserving the leading space character? – wilhelmtell May 07 '10 at 11:57
  • 2
    supporting escape characters in git's commit message wouldn't be such a big deal – knittl May 07 '10 at 11:59
  • 6
    It's a perfectly reasonable feature request. Especially in light of the fact that Trac, AFAICT, doesn't associate a commit to a bug slip if the commit message doesn't start with the slip number, starting with a hash. So it's not just someone's standards, it's a tool's required syntax. Let the Git devs decide whether it's worthwhile or not. (And yes, Trac could *also* fix the problem. There's nothing wrong with requesting that Git do what it can, too.) – Luke Maurer Mar 12 '11 at 00:05
  • “Especially in light of the fact that Trac, AFAICT, doesn't associate a commit to a bug slip if the commit message doesn't start with the slip number, starting with a hash.” — in my limited experience with Trac, something like `#xxx` occurring anywhere in the commit message will link to the issue. It doesn’t have to be at the start of the commit. Maybe this is something that has changed in the last five years? – Guildenstern Nov 06 '16 at 14:53
  • We use ### markdown in our github pull request templates, and since github will take a single-commit PR's commit message as the PR description, its handy to have the same commit template as the PR template. Then you can handle the commit message and the PR description in one shot. But this git behavior nukes the ### heading markdown – David Mann Aug 23 '18 at 20:34
0

! is a history expansion that's why it didn't worked.

History expansions are introduced by the appearance of the history expansion character, which is ! by default.

You can use $ with single ' quotes (Escape a Single Quote in Single Quote String in Bash):

$ git commit -m $'#228 update to a new version! margin of error is 33% | 33^*0.22;'
# commit message: #228 update to a new version! margin of error is 33% | 33^*0.22;
$ git commit -m $'docs!: new API reference for GPS horse navigation'
# commit message: docs!: new API reference for GPS horse navigation

If used without $ and ' but with ":

$ git commit -m "docs!: new API reference for GPS horse navigation"
bash:  : unrecognized history modifier

If used with " and escape \ (\ will still be there or I was doing something wrong):

$ git commit -m "docs\!: new API reference for GPS horse navigation"
# commit message: docs\!: new API reference for GPS horse navigation
Dmitriy Zub
  • 1,398
  • 8
  • 35
  • 1
    How does this answer the question of having a `#` as first character in a commit message? This answer doesn't even contain a `#` (except for comments) – knittl Sep 29 '22 at 06:55
  • @knittl answer (using `$` with `'`) meant to escape any characters, including `#`. I've updated the answer. – Dmitriy Zub Sep 29 '22 at 10:55
  • But it's not required, simply use single quotes and `git commit -m '…'`. This has been part of all answers here for the last 12 years. I don't see which new information this answer adds, except explaining shell quoting rules which are not what the question is about. The `$` is not required in any of your commands (and only works in bash) – knittl Sep 29 '22 at 11:05