zsh shell does not recognize git HEAD^
Asked Answered
A

4

18

I am using zsh shell and prezto with cygwin. When I type this git command:

git reset HEAD5

zsh returns:

zsh: no matches found: HEAD^

But when I switch to use bash shell, it works.

Why does zsh throw an error when I try to use HEAD^?

Asha answered 10/10, 2014 at 4:53 Comment(1)
Found this GitHub issueMassive
P
36

The ^ character is treated as special in filename expansions in zsh, but only if the EXTENDED_GLOB option is set:

zsh% setopt noEXTENDED_GLOB
zsh% echo HEAD^
HEAD^
zsh% setopt EXTENDED_GLOB
zsh% echo HEAD^
zsh: no matches found: HEAD^
zsh% 

Bash doesn't have this feature. (To be precise, bash does have an extended glob feature, enabled by shopt -s extglob, but bash's extended glob syntax doesn't treat the ^ character as special.)

With this feature enabled, ^ is a special character similar to * but with a different meaning. Like *, you can inhibit its special meaning by escaping it, either by enclosing it in single or double quotes or by preceding it with a backslash. Quoting is the simplest solution.

Rather than

git reset HEAD^

try this:

git reset 'HEAD^'

The meaning of the ^ wildcard is not relevant, since all you need to do is avoid using it, but I'll mention it anyway. According to the zsh manual, ^X matches anything except the pattern X. For the case of HEAD^, nothing follows the ^ -- which means that HEAD^ matches HEAD followed by anything other than nothing. That's a roundabout way of saying that HEAD^ matches file names starting with HEAD and followed by some non-empty string. Given files HEAD, HEAD1, and HEAD2, the pattern HEAD^ matches HEAD1 and HEAD2.

Practiced answered 10/10, 2014 at 9:2 Comment(0)
O
7

A quick workaround to avoid the ^ character is to use git reset head~1 instead of git reset head^.

See this post for the difference between the two.

Overcompensation answered 18/4, 2016 at 14:29 Comment(0)
S
4

issue 449 of oh-my-zsh describes this exact behaviour and provides the solution.

The culprit is the option extended_glob on zsh. Presto must be setting it. So when you type HEAD^ zsh tries to create a glob negation expression and fails with an error.

In other words, setopt extended_glob allows us to use ^ to negate globs.

To fix it, you can write this line on your .zshrc:

unsetopt nomatch 

With the above line, we are saying to zsh we want that when pattern matching fails, simply use the command "as is".

Stoddart answered 28/4, 2016 at 21:35 Comment(4)
Not recommended to unset nomatch just to avoid this error. This will have knock-on behaviour for all other shell code that the user might not want or expect. It's probably better to quote the string git reset "HEAD^", escape the character git reset HEAD\^ or use a tilde if it's appropriate git reset HEAD~1Tepper
I don't see a problem with that since scripts can use #!/usr/bin/env zsh -f and I'm not sure that using #!/usr/bin/env zsh makes the script pick up configuration from ~/.zshrc. If it does that could be a problem. And even then the script should set it's own options just to be sure. It should not be dependent on users specific configurations.Stoddart
That's true, but I would still hesitate doing it on my system at least because it changes the expected behaviour of globbing patterns that could catch you out if you're not mindful. For example, var=(*.fooext) with nomatch unset will not produce an error if the glob match fails, it will instead create a string called "*.fooext" in the var array. And that might not be what you expect. Then again, these might just be edge cases, and I guess it's up to the user to decide for themselves the system they want...Tepper
sh and ksh don't default to abort on glob mismatch from the zsh docs, so I think most script tend to target sh compatibility maybe?Womb
J
0

On Mac escape the ^ in your command:

git reset --soft HEAD\^
Julide answered 17/2, 2022 at 23:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.