Search code examples
windowsgitpowershellquoting

How can I fix conflicting symbols between git and powershell?


When I’m specifying gitrevisions in pwsh (eg HEAD@{3}), I have to conditionally remember to surround the gitrevision with quotes. If I don’t, it treats “@“ as an array sub-expression operator.

Example:

pwsh$ git checkout HEAD@{3}

fatal: ambiguous argument ‘HEAD@‘: unknown revision or path not in the
working tree

How can I configure git (2.44.0) or pwsh (7.4.2) to prevent these conflicting symbols?

I've tried using git and pwsh aliases, but they both only alias to commands.


Solution

  • How can I configure git (2.44.0) or pwsh (7.4.2) to prevent these conflicting symbols?

    You cannot. You cannot escape the syntax rules of the shell you're using.

    PowerShell is unusual in that it has more metacharacters (characters with special meaning) than other shells, notably including @ { } , ; ` (see this answer for details).

    To use these characters verbatim, you need to:

    • either: escape those individually, using ` (backtick), PowerShell's escape character.

      • E.g., git ... HEAD@`{3`} - note that @ does not need escaping in this case, because it occurs in the interior of the argument.
    • or: enclose the entire argument containing metacharacters in quotes (either '...' to create verbatim strings, or "..." for expandable (interpolating ones).

      • E.g., git ... 'HEAD@{3}'

    There is a - severely limited - way to prevent PowerShell from applying its usual parsing rules, namely --%, the stop-parsing token (see the bottom section of this answer for a summary of the limitations).
    However, you still need to remember to use it when needed.[1]

    • E.g., git ... --% HEAD@{3}

    I have to conditionally remember to surround it with quotes.

    If you don't want to learn which (additional) characters need escaping / quoting in PowerShell, your only option is to call a different shell, such as cmd.exe on Windows, and pass the command line to invoke as a single string.
    However, this can pose quoting challenges and comes with a performance penalty.

    • E.g., cmd /c 'git ... HEAD@{3}'

    [1] To ease the pain of typing --%, jthill suggests defining a keyboard shortcut such as Alt+/ that automatically inserts it. You can do so by placing the following in your $PROFILE file:
    Set-PSReadLineKeyHandler -Chord Alt+/ -ScriptBlock { [Microsoft.PowerShell.PSConsoleReadLine]::Insert('--%') }.
    Note that on Unix-like platforms the set of key chords available to the PSReadLine module is limited, as discussed in this GitHub comment; e.g. Ctrl+/ works only on Windows.