Search code examples
gitsedquoting

Git filter and sed fight over `\$`


I am trying to write a git filter using sed

[filter "revisioner"]
        smudge = sed -e "s/\\\$Revision\\\$/\$Revision: $(GIT_EXEC_PATH=/usr/lib/git-core/ git describe --tag svn)\$/g"
        clean = sed -e "s/\\\$Revision: [^$]*\\\$/\$Revision\$/g"

For sed to do the correct thing it wants to have an odd number of \ to escape the $, however git complains about an odd number of \ with:

fatal: bad config line 2 in file .git/../.gitconfig

I don't really want to move my sed script into an external command because it is yet an other moving part my users need to setup on their system, before using my repository.

Any advice?


Solution

  • Getting escape parsing right is often a challenge, as you have to think about each program that will parse the command, and you have to think about them in order.

    torek's answer has outlined the basic reasoning that applies to your case. I will add the following, because I think the end result is a bit more readable:

    First, to get the underlying sed script to work at the command line - converting, in my test, $HI$ to $Hello, World$ - I used

    sed -e 's/\$HI\$/$Hello World$/g'
    

    The single-quotes prevent bash from messing with the escapes, so sed sees \$ and matches a literal $. Note that the output pattern doesn't require this escaping.

    Then to put this in the .git/config file, double each backslash, giving

    clean = sed -e 's/\\$HI\\$/$Hello World$/g'
    

    This works in my tests; if it doesn't work for you, we may need more information to understand what's going on.