Skip to contentSkip to conversation

Unexpected recursion in 'git rm'

DISCUSSION Евгений Плискин 6 participants 8 messages Jul 2 – Jul 3 2 messages not in the archive

lore
Share & tools
lore
#1 lore raw
Quoted 9 lines · Евгений Плискин

Hello.

The following git command does recurse directories as contrary to the reference (https://git-scm.com/docs/git-rm):

git rm -n *.json

Without directory specification before '*.json' this command is not expected to recurse directories, but it really does.

git version 2.55.0.windows.1

Hi - I threw a quick test repo together, but did not see the result you describe. Could you produce a script or series of commands to reproduce the problem?

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw
Quoted 7 lines · Евгений Плискин
Quoted 1 line

Hi - I threw a quick test repo together, but did not see the result you describe. Could you produce a script or series of commands to reproduce the problem?

Hi. Thank you for your reply.
I was advised meantime that indeed this behaviour is expected:

This is expected behaviour, as the argument to git-rm(1) is a pathspec, and "*" matches directory separators by default, see also gitglossary(7) under "pathspec":

Yup, I see that now, and that was the difference maker in my test. I had json files in the directory I was working, as well as at nested paths. My (non-windows) shell globbed to pass just the upper files.

To address Patrick's question in <[email protected]>:

Quoted 2 lines

Could you maybe clarify which part of git-rm(1) made you think that this wouldn't happen?

I'll say that I _don't_ think the man page is unclear in this regard (having given it a look just now). To me, this is just one of the aspects of git that is integrated with its unix counterpart well enough (git-rm vs. rm) that you can forget the finer details like this fairly easily.

And since the command is so straightforward, I couldn't tell you the last time I pulled up git-rm(1) as a reference.

#4 lore raw
In reply to Евгений Плискин

Hi,

Quoted 9 lines · Евгений Плискин

Hello.

The following git command does recurse directories as contrary to the reference (https://git-scm.com/docs/git-rm):

git rm -n *.json

Without directory specification before '*.json' this command is not expected to recurse directories, but it really does.

This is expected behaviour, as the argument to git-rm(1) is a pathspec, and "*" matches directory separators by default, see also gitglossary(7) under "pathspec":

• the pathspec up to the last slash represents a directory prefix. The scope of that pathspec is limited to that subtree.

• the rest of the pathspec is a pattern for the remainder of the pathname. Paths relative to the directory prefix will be matched against that pattern using fnmatch(3); in particular, * and ? can match directory separators.

For example, Documentation/*.jpg will match all .jpg files in the Documentation subtree, including Documentation/chapter_1/figure_1.jpg.

Could you maybe clarify which part of git-rm(1) made you think that this wouldn't happen?

Thanks!

Patrick

#5 lore raw
Quoted 10 lines · Patrick Steinhardt
Quoted 9 lines · Евгений Плискин

Hello.

The following git command does recurse directories as contrary to the reference (https://git-scm.com/docs/git-rm):

git rm -n *.json

Without directory specification before '*.json' this command is not expected to recurse directories, but it really does.

Are there any ".json" files in the directory where you're running this? As the glob is not quoted, I think maybe what is happening is that there are no matching files in the current directory so the shell is not expanding the glob as you expect and is passing it to git which treats it as Patrick explains below.

Thanks

Phillip

Quoted 22 lines

This is expected behaviour, as the argument to git-rm(1) is a pathspec, and "*" matches directory separators by default, see also gitglossary(7) under "pathspec":

• the pathspec up to the last slash represents a directory prefix. The scope of that pathspec is limited to that subtree.

• the rest of the pathspec is a pattern for the remainder of the pathname. Paths relative to the directory prefix will be matched against that pattern using fnmatch(3); in particular, * and ? can match directory separators.

For example, Documentation/*.jpg will match all .jpg files in the Documentation subtree, including Documentation/chapter_1/figure_1.jpg.

Could you maybe clarify which part of git-rm(1) made you think that this wouldn't happen?

Thanks!

Patrick

A message that is not in the archive (sent off-list or not yet received): [email protected]

#7 lore raw

Adding the mailing list back into Cc.

Quoted 10 lines · Евгений Плискин
Quoted 5 lines

This is expected behaviour, as the argument to git-rm(1) is a pathspec, and "*" matches directory separators by default, see also gitglossary(7) under "pathspec":
• the pathspec up to the last slash represents a directory prefix. The scope of that pathspec is limited to that subtree.
• the rest of the pathspec is a pattern for the remainder of the pathname. Paths relative to the directory prefix will be matched against that pattern using fnmatch(3); in particular, * and ? can match directory separators. For example, Documentation/*.jpg will match all .jpg files in the Documentation subtree, including Documentation/chapter_1/figure_1.jpg.
Could you maybe clarify which part of git-rm(1) made you think that this wouldn't happen?

Thank you for your reply. I believe you are correct.

I have made more research and found a way to remove files in current directory only without recursion into subdirectories:

     git rm -n ':(glob)*.json'

Yup, that wouldn't cross directory separators indeed.

Patrick

#8 lore raw
In reply to Евгений Плискин
Quoted 10 lines · Евгений Плискин

Hello.

The following git command does recurse directories as contrary to the reference (https://git-scm.com/docs/git-rm):

git rm -n *.json

Without directory specification before '*.json' this command is not expected to recurse directories, but it really does.

git version 2.55.0.windows.1

I can't see any formulation in the manpage reference that suggests it wouldn't recurse, though you might overall get less surprised if you set the failglob option in bash. Then the shell would notice *.json has no matches, and you'd have to say git rm -n '*.json' to let git process the glob instead of the shell. See also
https://git-scm.com/docs/gitglossary (as referenced from the git-rm page) which says:

the rest of the pathspec is a pattern for the remainder of the pathname. Paths relative to the directory prefix will be matched against that pattern using fnmatch(3); in particular, * and ? can match directory separators.

Signature · 1 line
Mikael Magnusson
#9 lore raw
Quoted 2 lines · Mikael Magnusson

..., though you might overall get less surprised if you set the failglob option in bash.

Excellent suggestion.