git@vger.kernel.org mailing list mirror (one of many)
 help / Atom feed
* "git rm" seems to do recursive removal even without "-r"
@ 2017-10-07 18:39 Robert P. J. Day
  2017-10-07 19:04 ` Todd Zullinger
  0 siblings, 1 reply; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 18:39 UTC (permalink / raw)
  To: Git Mailing list


  was just testing variations of "git rm", and man page claims:

  -r
     Allow recursive removal when a leading directory name is given.

i tested this on the "pro git" book repo, which contains a top-level
"book/" directory, and quite a number of "*.asc" files in various
subdirectories one or more levels down. i ran:

  $ git rm book/\*.asc

and it certainly seemed to delete *all* "*.asc" files no matter where
they were under book/, even without the "-r" option.

  am i misunderstanding something?

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 18:39 "git rm" seems to do recursive removal even without "-r" Robert P. J. Day
@ 2017-10-07 19:04 ` Todd Zullinger
  2017-10-07 19:12   ` Robert P. J. Day
  0 siblings, 1 reply; 29+ messages in thread
From: Todd Zullinger @ 2017-10-07 19:04 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Git Mailing list

Robert P. J. Day wrote:
>
>  was just testing variations of "git rm", and man page claims:
>
>  -r 
>     Allow recursive removal when a leading directory name is given.
>
> i tested this on the "pro git" book repo, which contains a top-level 
> "book/" directory, and quite a number of "*.asc" files in various 
> subdirectories one or more levels down. i ran:
>
>  $ git rm book/\*.asc
>
> and it certainly seemed to delete *all* "*.asc" files no matter where 
> they were under book/, even without the "-r" option.
>
>  am i misunderstanding something?

By shell-escaping the *, you're letting git perform the file glob.  
The DISCUSSION section of git-rm(1) says "File globbing matches across 
directory boundaries."

# With bash performing file globbing
$ git rm -n Documentation/*.txt | wc -l
199

# With git performing file globbing
$ git rm -n Documentation/\*.txt | wc -l
578

-- 
Todd
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Whenever you find yourself on the side of the majority, it is time to
pause and reflect.
    -- Mark Twain


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:04 ` Todd Zullinger
@ 2017-10-07 19:12   ` Robert P. J. Day
  2017-10-07 19:29     ` Jeff King
  0 siblings, 1 reply; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 19:12 UTC (permalink / raw)
  To: Todd Zullinger; +Cc: Git Mailing list

On Sat, 7 Oct 2017, Todd Zullinger wrote:

> Robert P. J. Day wrote:
> >
> >  was just testing variations of "git rm", and man page claims:
> >
> >  -r     Allow recursive removal when a leading directory name is given.
> >
> > i tested this on the "pro git" book repo, which contains a top-level "book/"
> > directory, and quite a number of "*.asc" files in various subdirectories one
> > or more levels down. i ran:
> >
> >  $ git rm book/\*.asc
> >
> > and it certainly seemed to delete *all* "*.asc" files no matter where they
> > were under book/, even without the "-r" option.
> >
> >  am i misunderstanding something?
>
> By shell-escaping the *, you're letting git perform the file glob.  The
> DISCUSSION section of git-rm(1) says "File globbing matches across directory
> boundaries."
>
> # With bash performing file globbing
> $ git rm -n Documentation/*.txt | wc -l
> 199
>
> # With git performing file globbing
> $ git rm -n Documentation/\*.txt | wc -l
> 578

  ok, in that case, can you give me an example where "-r" makes a
difference, given that the man page refers to "a leading directory
name being given"? let's use as an example the linux kernel source,
where there are a *ton* of files named "Makefile" under the drivers/
directory.

  should there be a difference between:

  $ git rm drivers/Makefile
  $ git rm -r drivers/Makefile

clearly, i have a "leading directory name" in both examples above ...
what should happen differently?

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:12   ` Robert P. J. Day
@ 2017-10-07 19:29     ` Jeff King
  2017-10-07 19:32       ` Robert P. J. Day
  0 siblings, 1 reply; 29+ messages in thread
From: Jeff King @ 2017-10-07 19:29 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Todd Zullinger, Git Mailing list

On Sat, Oct 07, 2017 at 03:12:01PM -0400, Robert P. J. Day wrote:

>   ok, in that case, can you give me an example where "-r" makes a
> difference, given that the man page refers to "a leading directory
> name being given"? let's use as an example the linux kernel source,
> where there are a *ton* of files named "Makefile" under the drivers/
> directory.
> 
>   should there be a difference between:
> 
>   $ git rm drivers/Makefile
>   $ git rm -r drivers/Makefile
> 
> clearly, i have a "leading directory name" in both examples above ...
> what should happen differently?

Nothing, because there is nothing to recurse in the pathspecs you've
given.

Try:

  $ git rm drivers
  fatal: not removing 'drivers' recursively without -r

versus

  $ git rm -r drivers
  [...removes everything under drivers/...]

-Peff

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:29     ` Jeff King
@ 2017-10-07 19:32       ` Robert P. J. Day
  2017-10-07 19:38         ` Jeff King
  0 siblings, 1 reply; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 19:32 UTC (permalink / raw)
  To: Jeff King; +Cc: Todd Zullinger, Git Mailing list

On Sat, 7 Oct 2017, Jeff King wrote:

> On Sat, Oct 07, 2017 at 03:12:01PM -0400, Robert P. J. Day wrote:
>
> >   ok, in that case, can you give me an example where "-r" makes a
> > difference, given that the man page refers to "a leading directory
> > name being given"? let's use as an example the linux kernel source,
> > where there are a *ton* of files named "Makefile" under the drivers/
> > directory.
> >
> >   should there be a difference between:
> >
> >   $ git rm drivers/Makefile
> >   $ git rm -r drivers/Makefile
> >
> > clearly, i have a "leading directory name" in both examples above ...
> > what should happen differently?
>
> Nothing, because there is nothing to recurse in the pathspecs you've
> given.
>
> Try:
>
>   $ git rm drivers
>   fatal: not removing 'drivers' recursively without -r
>
> versus
>
>   $ git rm -r drivers
>   [...removes everything under drivers/...]

  that is not what the man page is saying ... it refers to a "leading"
directory name, not simply a directory name. if it should say simply
"when a directory name is given", then it should be changed to say
that.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:32       ` Robert P. J. Day
@ 2017-10-07 19:38         ` Jeff King
  2017-10-07 19:43           ` Robert P. J. Day
  0 siblings, 1 reply; 29+ messages in thread
From: Jeff King @ 2017-10-07 19:38 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Todd Zullinger, Git Mailing list

On Sat, Oct 07, 2017 at 03:32:24PM -0400, Robert P. J. Day wrote:

> > Nothing, because there is nothing to recurse in the pathspecs you've
> > given.
> >
> > Try:
> >
> >   $ git rm drivers
> >   fatal: not removing 'drivers' recursively without -r
> >
> > versus
> >
> >   $ git rm -r drivers
> >   [...removes everything under drivers/...]
> 
>   that is not what the man page is saying ... it refers to a "leading"
> directory name, not simply a directory name. if it should say simply
> "when a directory name is given", then it should be changed to say
> that.

It's the leading directory of the files that will be removed.

An earlier part of the manpage (under <file>) also says:

  A leading directory name (e.g. dir to remove dir/file1 and dir/file2)
  can be given to remove all files in the directory, and recursively all
  sub-directories, but this requires the -r option to be explicitly
  given.

which perhaps makes it more clear. Later in "-r", we say:

   -r
           Allow recursive removal when a leading directory name is given.

which I guess is the part you're reading.  I think it would be equally
correct to say "leading directory" or just "directory" there.

Though really, you could give many such directory names, or even match
them with a glob. So a more accurate description might be something
like:

  -r
	Recursively remove the contents of any directories that match
	`<file>`.

or something.

-Peff

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:38         ` Jeff King
@ 2017-10-07 19:43           ` Robert P. J. Day
  2017-10-07 21:05             ` Theodore Ts'o
  2017-10-07 21:44             ` Paul Smith
  0 siblings, 2 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 19:43 UTC (permalink / raw)
  To: Jeff King; +Cc: Todd Zullinger, Git Mailing list

On Sat, 7 Oct 2017, Jeff King wrote:

> On Sat, Oct 07, 2017 at 03:32:24PM -0400, Robert P. J. Day wrote:
>
> > > Nothing, because there is nothing to recurse in the pathspecs you've
> > > given.
> > >
> > > Try:
> > >
> > >   $ git rm drivers
> > >   fatal: not removing 'drivers' recursively without -r
> > >
> > > versus
> > >
> > >   $ git rm -r drivers
> > >   [...removes everything under drivers/...]
> >
> >   that is not what the man page is saying ... it refers to a "leading"
> > directory name, not simply a directory name. if it should say simply
> > "when a directory name is given", then it should be changed to say
> > that.
>
> It's the leading directory of the files that will be removed.
>
> An earlier part of the manpage (under <file>) also says:
>
>   A leading directory name (e.g. dir to remove dir/file1 and dir/file2)
>   can be given to remove all files in the directory, and recursively all
>   sub-directories, but this requires the -r option to be explicitly
>   given.
>
> which perhaps makes it more clear. Later in "-r", we say:
>
>    -r
>            Allow recursive removal when a leading directory name is given.
>
> which I guess is the part you're reading.  I think it would be equally
> correct to say "leading directory" or just "directory" there.
>
> Though really, you could give many such directory names, or even match
> them with a glob. So a more accurate description might be something
> like:
>
>   -r
> 	Recursively remove the contents of any directories that match
> 	`<file>`.
>
> or something.

  it's been a long week, so take this in the spirit in which it is
intended ... i think the "git rm" command and its man page should be
printed out, run through a paper shredder, then set on fire. i can't
remember the last time i saw such a thoroughly badly-designed,
badly-documented and non-intuitive utility.

  i'm going to go watch football now and try to forget this horror.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:43           ` Robert P. J. Day
@ 2017-10-07 21:05             ` Theodore Ts'o
  2017-10-07 21:40               ` Robert P. J. Day
  2017-10-07 21:44             ` Paul Smith
  1 sibling, 1 reply; 29+ messages in thread
From: Theodore Ts'o @ 2017-10-07 21:05 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Jeff King, Todd Zullinger, Git Mailing list

On Sat, Oct 07, 2017 at 03:43:43PM -0400, Robert P. J. Day wrote:
> >   -r
> > 	Recursively remove the contents of any directories that match
> > 	`<file>`.
> >
> > or something.
> 
>   it's been a long week, so take this in the spirit in which it is
> intended ... i think the "git rm" command and its man page should be
> printed out, run through a paper shredder, then set on fire. i can't
> remember the last time i saw such a thoroughly badly-designed,
> badly-documented and non-intuitive utility.
> 
>   i'm going to go watch football now and try to forget this horror.

It sounds like the real issue here is that you are interpreting
"recursively" to mean "globbing".  Your original complaint seemed to
be a surprise that "git rm book/\*.asc" would delete all of the files
in the directory "book" that ended in .asc, even without the -r flag.

That's because the operation of matching *.asc is considered
"globbing".  Now if there were directories whose name ended in .asc,
then they would only be deleted if the -r flag is given.  Deleting
directories and their contents is what is considered "recursive
removal".

That's not particularly surprising to me as a long-time Unix/Linux
user/developer, since that's how things work in Unix/Linux:

% touch 1.d 2.d ; mkdir 3.d 4.d
% /bin/ls
1.d  2.d  3.d  4.d
% rm -r *.d
% touch 1.d 2.d ; mkdir 3.d 4.d
% rm *.d
rm: cannot remove '3.d': Is a directory
rm: cannot remove '4.d': Is a directory

I'm going to guess that you don't come from a Unix background?

        	     	   	    - Ted

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 21:05             ` Theodore Ts'o
@ 2017-10-07 21:40               ` Robert P. J. Day
  0 siblings, 0 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 21:40 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Jeff King, Todd Zullinger, Git Mailing list

On Sat, 7 Oct 2017, Theodore Ts'o wrote:

> On Sat, Oct 07, 2017 at 03:43:43PM -0400, Robert P. J. Day wrote:
> > >   -r
> > > 	Recursively remove the contents of any directories that match
> > > 	`<file>`.
> > >
> > > or something.
> >
> >   it's been a long week, so take this in the spirit in which it is
> > intended ... i think the "git rm" command and its man page should be
> > printed out, run through a paper shredder, then set on fire. i can't
> > remember the last time i saw such a thoroughly badly-designed,
> > badly-documented and non-intuitive utility.
> >
> >   i'm going to go watch football now and try to forget this horror.
>
> It sounds like the real issue here is that you are interpreting
> "recursively" to mean "globbing".  Your original complaint seemed to
> be a surprise that "git rm book/\*.asc" would delete all of the files
> in the directory "book" that ended in .asc, even without the -r flag.
>
> That's because the operation of matching *.asc is considered
> "globbing".  Now if there were directories whose name ended in .asc,
> then they would only be deleted if the -r flag is given.  Deleting
> directories and their contents is what is considered "recursive
> removal".
>
> That's not particularly surprising to me as a long-time Unix/Linux
> user/developer, since that's how things work in Unix/Linux:
>
> % touch 1.d 2.d ; mkdir 3.d 4.d
> % /bin/ls
> 1.d  2.d  3.d  4.d
> % rm -r *.d
> % touch 1.d 2.d ; mkdir 3.d 4.d
> % rm *.d
> rm: cannot remove '3.d': Is a directory
> rm: cannot remove '4.d': Is a directory
>
> I'm going to guess that you don't come from a Unix background?

  yeah, that must be it, i'm a newbie at linux. let's go with that.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 19:43           ` Robert P. J. Day
  2017-10-07 21:05             ` Theodore Ts'o
@ 2017-10-07 21:44             ` Paul Smith
  2017-10-07 21:55               ` Robert P. J. Day
  1 sibling, 1 reply; 29+ messages in thread
From: Paul Smith @ 2017-10-07 21:44 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Git Mailing list

On Sat, 2017-10-07 at 15:43 -0400, Robert P. J. Day wrote:
>   it's been a long week, so take this in the spirit in which it is
> intended ... i think the "git rm" command and its man page should be
> printed out, run through a paper shredder, then set on fire. i can't
> remember the last time i saw such a thoroughly badly-designed,
> badly-documented and non-intuitive utility.

"git rm" works the same way that the UNIX rm command has worked, for 40+
years now.  Very simple, very well designed, and very intuitive (IMO).

The major difference is the ability to handle globbing patterns, which
UNIX rm doesn't do.  Maybe the way this is implemented is a little
confusing, although I just read the man page and it seemed pretty clear
to me.

If you don't use glob patterns (or more specifically if you let the
shell handle glob patterns, which is how I always do it) then there is
really nothing bizarre about "git rm".  Maybe you could be more precise
in your criticism.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 21:44             ` Paul Smith
@ 2017-10-07 21:55               ` Robert P. J. Day
  2017-10-08  4:20                 ` Junio C Hamano
  2017-10-08 14:32                 ` Paul Smith
  0 siblings, 2 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-07 21:55 UTC (permalink / raw)
  To: Paul Smith; +Cc: Git Mailing list

[-- Attachment #1: Type: text/plain, Size: 2234 bytes --]

On Sat, 7 Oct 2017, Paul Smith wrote:

> On Sat, 2017-10-07 at 15:43 -0400, Robert P. J. Day wrote:
> >   it's been a long week, so take this in the spirit in which it is
> > intended ... i think the "git rm" command and its man page should be
> > printed out, run through a paper shredder, then set on fire. i can't
> > remember the last time i saw such a thoroughly badly-designed,
> > badly-documented and non-intuitive utility.
>
> "git rm" works the same way that the UNIX rm command has worked, for
> 40+ years now.  Very simple, very well designed, and very intuitive
> (IMO).
>
> The major difference is the ability to handle globbing patterns,
> which UNIX rm doesn't do.  Maybe the way this is implemented is a
> little confusing, although I just read the man page and it seemed
> pretty clear to me.

  um, wrong.

> If you don't use glob patterns (or more specifically if you let the
> shell handle glob patterns, which is how I always do it) then there
> is really nothing bizarre about "git rm".  Maybe you could be more
> precise in your criticism.

  ok, fine, let me explain why this command is a nightmarish
monstrosity. as i now understand, if i use an escaped wildcard
pattern, "git rm" will *automatically* (with no further guidance from
me, and no warning), operate recursively. so if, in the kernel source
tree, i ran:

  $ git rm \*.c

i would end up removing *all* 25,569 "*.c" files in the kernel source
repository.

  however, let's say i wanted to remove, recursively, all files with a
*precise* (non-globbed) name, such as "Makefile". so i, naively, run:

  $ git rm Makefile

guess what ... the lack of globbing means i remove only the single
Makefile at the top of the working directory.

  if that isn't an example of ridiculous, non-intuitive behaviour, i
don't know what is.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 21:55               ` Robert P. J. Day
@ 2017-10-08  4:20                 ` Junio C Hamano
  2017-10-08  9:07                   ` Robert P. J. Day
  2017-10-08 11:56                   ` Robert P. J. Day
  2017-10-08 14:32                 ` Paul Smith
  1 sibling, 2 replies; 29+ messages in thread
From: Junio C Hamano @ 2017-10-08  4:20 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Paul Smith, Git Mailing list

"Robert P. J. Day" <rpjday@crashcourse.ca> writes:

> ... so if, in the kernel source
> tree, i ran:
>
>   $ git rm \*.c
>
> i would end up removing *all* 25,569 "*.c" files in the kernel source
> repository.

Yes, as that is exactly what the command line asks Git to do.

If you said

    $ git rm *.c

then the shell expands the glob and all Git sees is that you want to
remove a.c b.c d.c ...; if you said "git rm -r *.c", unless b.c is
not a directory, these and only these files are removed.

>   however, let's say i wanted to remove, recursively, all files with a
> *precise* (non-globbed) name, such as "Makefile". so i, naively, run:
>
>   $ git rm Makefile
>
> guess what ... the lack of globbing means i remove only the single
> Makefile at the top of the working directory.

Again, that is exactly what you asked Git to do.

    $ git rm $(find . -name Makefile -print)

would of course one way to remove all Makefiles.  If you let POSIX
shell glob, i.e.

    $ git rm */Makefile

the asterisk would not expand nothing but a single level, so it may
remove fs/Makefile, but not fs/ext4/Makefile (some shells allow
"wildmatch" expansion so "git rm **/Makefile" may catch the latter
with such a shell).

By letting Git see the glob, i.e.

    $ git rm Makefile \*/Makefile

you would let Git to go over the paths it knows/cares about to find
ones that match the pathspec pattern and remove them (but not
recursively, even if you had a directory whose name is Makefile; for
that, you would use "-r").

Earlier some people mentioned "Unix newbie" in the thread, but I do
not think this is about Unix.  In general, Unix tools do not perform
grobbing themselves but expect the user to tell the shell to do so
before the tools see the arguments.  In that sense, I do think the
combination of "-r" and globbing pathspec may produce a result that
looks confusing at first glance.  

"git rm [-r] <pathspec>..."

 (1) walks the paths it knows/cares about, rejecting ones that do
     not match the <pathspec>;

 (2) decides to remove the ones that match; and

 (3) when it is asked to recursively remove, the ones that are
     directories are removed together with its contents.  If it was
     not asked to go recursive, it refuses to act on directories.

where (1) and (2) are not something the tool needs to worry
about---what is given from the command line is the only set of paths
that the tool is asked to operate on.  These two steps are quite
unlike regular Unix tools.

Once you decide to give the tool the flexibility that come from
taking pathspec, however, steps (1) and (2) do have to happen inside
the tool.  And great power takes some understanding of the tool on
the part of the user to exercise.  I suspect that the occasion you
would need to use "-r" with "git rm" is a lot less frequent than a
plain "rm".

Of course, there is no confusion if you do not quote wildcards.  By
quoting wildcards and not letting the shell to expand them, the user
tells Git that the fact _it_ sees the asterisk is because the user
is doing so on purpose---so that Git would find paths that match the
pattern.

Hope this clarifies and helps.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08  4:20                 ` Junio C Hamano
@ 2017-10-08  9:07                   ` Robert P. J. Day
  2017-10-08 11:37                     ` Kevin Daudt
  2017-10-08 11:56                   ` Robert P. J. Day
  1 sibling, 1 reply; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-08  9:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Paul Smith, Git Mailing list

On Sun, 8 Oct 2017, Junio C Hamano wrote:

> "Robert P. J. Day" <rpjday@crashcourse.ca> writes:
>
> > ... so if, in the kernel source
> > tree, i ran:
> >
> >   $ git rm \*.c
> >
> > i would end up removing *all* 25,569 "*.c" files in the kernel source
> > repository.
>
> Yes, as that is exactly what the command line asks Git to do.

  so if i wanted git to remove, say, all files named "Makefile*" from
everywhere in the linux kernel source tree, the (dry run) command
would be:

  $ git rm -n Makefile\*

is that it? let's try that:

  $ git rm -n Makefile\*
  rm 'Makefile'
  $

oops.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08  9:07                   ` Robert P. J. Day
@ 2017-10-08 11:37                     ` Kevin Daudt
  0 siblings, 0 replies; 29+ messages in thread
From: Kevin Daudt @ 2017-10-08 11:37 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Junio C Hamano, Paul Smith, Git Mailing list

On Sun, Oct 08, 2017 at 05:07:12AM -0400, Robert P. J. Day wrote:
> On Sun, 8 Oct 2017, Junio C Hamano wrote:
> 
> > "Robert P. J. Day" <rpjday@crashcourse.ca> writes:
> >
> > > ... so if, in the kernel source
> > > tree, i ran:
> > >
> > >   $ git rm \*.c
> > >
> > > i would end up removing *all* 25,569 "*.c" files in the kernel source
> > > repository.
> >
> > Yes, as that is exactly what the command line asks Git to do.
> 
>   so if i wanted git to remove, say, all files named "Makefile*" from
> everywhere in the linux kernel source tree, the (dry run) command
> would be:
> 
>   $ git rm -n Makefile\*
> 
> is that it? let's try that:
> 
>   $ git rm -n Makefile\*
>   rm 'Makefile'
>   $
> 
> oops.
> 
> rday
> 

So your question is not su much  about the recursive option (delete
mentioned directories, including their contents), but globbing
(expanding the * to any files matching the pattern).

The explanation of <files> mentions this:

   Files to remove. Fileglobs (e.g.  *.c) can be given to remove all
   matching files.

This indicates that git itself (not your shell alone) does file
globbing.

I think the confusing part is that most people have no clear idea of the
separation between what the shell sees and interprets, and what the
program actually gets.

When you execute:

    $ git rm Makefile\*

What git actually sees is this:

    Makefile*

The shell intepreted the \* to mean just '*' and not interpret it
itself, and provide that to the executed program. Git, in its turn,
would start matching any file to that pattern to see which files
matches.


If you would execute:

    $ git rm 'Makefile\*'

Git would see:

    Makefile\*

Which does the thing you intended. So you have to deal with 2 levels of
programs interpreting the arguments, not just one.

Whether '*.c' should match just all .c files in the current dir, or all
files ending with .c depends on whether the path seperator is matched by
* or not and is a separate discussion.

GITGLOSSARY(7) under pathspec mentions this:

    glob    Git treats the pattern as a shell glob suitable for consumption
            by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the
            pattern will not match a / in the pathname.

So that seems to indicate '*.c' should only match .c files in the
current dir. I'm not sure why that's not the case.

I hope this clears up what's happening a bit, and perhaps can lead to
improvements to the documentation so that it's not so surprising.

Kind regards, Kevin.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08  4:20                 ` Junio C Hamano
  2017-10-08  9:07                   ` Robert P. J. Day
@ 2017-10-08 11:56                   ` Robert P. J. Day
  2017-10-08 12:23                     ` Martin Ågren
                                       ` (2 more replies)
  1 sibling, 3 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-08 11:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Paul Smith, Git Mailing list

On Sun, 8 Oct 2017, Junio C Hamano wrote:

> "Robert P. J. Day" <rpjday@crashcourse.ca> writes:
>
> > ... so if, in the kernel source
> > tree, i ran:
> >
> >   $ git rm \*.c
> >
> > i would end up removing *all* 25,569 "*.c" files in the kernel
> > source repository.
>
> Yes, as that is exactly what the command line asks Git to do.

  ok, i truly want to understand this, so let me dig through this
carefully. i can now see (from the man page and the recent
explanations) that "git rm" will accept *escaped* fileglobs to remove
and that, further, "File globbing matches across directory
boundaries." which is why, in the linux kernel source tree, if i run
one of:

  $ git rm \*.c
  $ git rm '*.c'

the "git rm" command will internally process the fileglob and apply it
across directory boundaries. and that's why, when i try a dry run, i
can see the effect it would have on the kernel source:

  $ git rm -n '*.c' | wc -l
  25569
  $

> If you said
>
>     $ git rm *.c
>
> then the shell expands the glob and all Git sees is that you want to
> remove a.c b.c d.c ...; if you said "git rm -r *.c", unless b.c is
> not a directory, these and only these files are removed.

  right, that's just regular shell fileglob processing, no surprise
there. (let's stick to just file removal for now.)

> >   however, let's say i wanted to remove, recursively, all files with a
> > *precise* (non-globbed) name, such as "Makefile". so i, naively, run:
> >
> >   $ git rm Makefile
> >
> > guess what ... the lack of globbing means i remove only the single
> > Makefile at the top of the working directory.
>
> Again, that is exactly what you asked Git to do.

  yes, now i get it -- a lack of fileglob arguments disallows
traversing directory boundaries, so one gets the "normal" behaviour.

>     $ git rm $(find . -name Makefile -print)
>
> would of course one way to remove all Makefiles.  If you let POSIX
> shell glob, i.e.
>
>     $ git rm */Makefile
>
> the asterisk would not expand nothing but a single level, so it may
> remove fs/Makefile, but not fs/ext4/Makefile (some shells allow
> "wildmatch" expansion so "git rm **/Makefile" may catch the latter
> with such a shell).

  sure, all regular shell fileglob processing.

> By letting Git see the glob, i.e.
>
>     $ git rm Makefile \*/Makefile
>
> you would let Git to go over the paths it knows/cares about to find
> ones that match the pathspec pattern and remove them (but not
> recursively, even if you had a directory whose name is Makefile; for
> that, you would use "-r").

  right ... i can now see that '*/Makefile' would pick up all
Makefiles *below* the current directory, so you need that initial
reference to 'Makefile' to catch the top one. this just seems ...
awkward.

  but as i asked in my earlier post, if i wanted to remove *all* files
with names of "Makefile*", why can't i use:

  $ git rm 'Makefile*'

just as i used:

  $ git rm '*.c'

are those not both acceptable fileglobs? why does the former clearly
only match the top-level Makefile, and refuse to cross directory
boundaries?

  $ git rm -n 'Makefile*'
  rm 'Makefile'
  $

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 11:56                   ` Robert P. J. Day
@ 2017-10-08 12:23                     ` Martin Ågren
  2017-10-08 12:39                     ` René Scharfe
  2017-10-10 11:52                     ` Heiko Voigt
  2 siblings, 0 replies; 29+ messages in thread
From: Martin Ågren @ 2017-10-08 12:23 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Junio C Hamano, Paul Smith, Git Mailing list

On 8 October 2017 at 13:56, Robert P. J. Day <rpjday@crashcourse.ca> wrote:
>   but as i asked in my earlier post, if i wanted to remove *all* files
> with names of "Makefile*", why can't i use:
>
>   $ git rm 'Makefile*'
>
> just as i used:
>
>   $ git rm '*.c'
>
> are those not both acceptable fileglobs? why does the former clearly
> only match the top-level Makefile, and refuse to cross directory
> boundaries?
>
>   $ git rm -n 'Makefile*'
>   rm 'Makefile'
>   $

Hmmm. The manpage says the following:

       git rm -f git-*.sh
           Because this example lets the shell expand the asterisk (i.e.
           you are listing the files explicitly), it does not remove
           subdir/git-foo.sh.

This implies that `git rm "git-*.sh"` should remove subdir/git-foo.sh.
But it doesn't, at least not in my testing. It seems that the globbing
only kicks in when the "*" comes first, as you've noted.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 11:56                   ` Robert P. J. Day
  2017-10-08 12:23                     ` Martin Ågren
@ 2017-10-08 12:39                     ` René Scharfe
  2017-10-08 12:45                       ` Robert P. J. Day
  2017-10-10 11:52                     ` Heiko Voigt
  2 siblings, 1 reply; 29+ messages in thread
From: René Scharfe @ 2017-10-08 12:39 UTC (permalink / raw)
  To: Git Mailing list; +Cc: Junio C Hamano, Paul Smith

[My SMTP server still refuses to accept emails to rpjday@crashcourse.ca
 and reports "mailbox unavailable" and "invalid DNS MX or A/AAAA resource
 record."  So just replying to the list.]

Am 08.10.2017 um 13:56 schrieb Robert P. J. Day:
>    but as i asked in my earlier post, if i wanted to remove *all* files
> with names of "Makefile*", why can't i use:
> 
>    $ git rm 'Makefile*'
> 
> just as i used:
> 
>    $ git rm '*.c'
> 
> are those not both acceptable fileglobs? why does the former clearly
> only match the top-level Makefile, and refuse to cross directory
> boundaries?
> 
>    $ git rm -n 'Makefile*'
>    rm 'Makefile'
>    $

Try:

	$ git rm -n '*Makefile'

The whole path is considered.  The asterisk there matches any
directory part -- but also any file name prefix.  Check the entry for
"pathspec" in gitglossary(7) for more details.

René

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 12:39                     ` René Scharfe
@ 2017-10-08 12:45                       ` Robert P. J. Day
  0 siblings, 0 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-08 12:45 UTC (permalink / raw)
  To: René Scharfe; +Cc: Git Mailing list, Junio C Hamano, Paul Smith

[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

On Sun, 8 Oct 2017, René Scharfe wrote:

> [My SMTP server still refuses to accept emails to rpjday@crashcourse.ca
>  and reports "mailbox unavailable" and "invalid DNS MX or A/AAAA resource
>  record."  So just replying to the list.]
>
> Am 08.10.2017 um 13:56 schrieb Robert P. J. Day:
> >    but as i asked in my earlier post, if i wanted to remove *all* files
> > with names of "Makefile*", why can't i use:
> >
> >    $ git rm 'Makefile*'
> >
> > just as i used:
> >
> >    $ git rm '*.c'
> >
> > are those not both acceptable fileglobs? why does the former clearly
> > only match the top-level Makefile, and refuse to cross directory
> > boundaries?
> >
> >    $ git rm -n 'Makefile*'
> >    rm 'Makefile'
> >    $
>
> Try:
>
> 	$ git rm -n '*Makefile'
>
> The whole path is considered.  The asterisk there matches any
> directory part -- but also any file name prefix.  Check the entry
> for "pathspec" in gitglossary(7) for more details.

  but "*Makefile" is not the wildcard pattern i'm interested in.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-07 21:55               ` Robert P. J. Day
  2017-10-08  4:20                 ` Junio C Hamano
@ 2017-10-08 14:32                 ` Paul Smith
  2017-10-08 18:40                   ` Theodore Ts'o
  1 sibling, 1 reply; 29+ messages in thread
From: Paul Smith @ 2017-10-08 14:32 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Git Mailing list

On Sat, 2017-10-07 at 17:55 -0400, Robert P. J. Day wrote:
> On Sat, 7 Oct 2017, Paul Smith wrote:
> > On Sat, 2017-10-07 at 15:43 -0400, Robert P. J. Day wrote:
> > > it's been a long week, so take this in the spirit in which it is
> > > intended ... i think the "git rm" command and its man page should be
> > > printed out, run through a paper shredder, then set on fire. i can't
> > > remember the last time i saw such a thoroughly badly-designed,
> > > badly-documented and non-intuitive utility.
> >
> > "git rm" works the same way that the UNIX rm command has worked, for
> > 40+ years now.  Very simple, very well designed, and very intuitive
> > (IMO).
> >
> > The major difference is the ability to handle globbing patterns,
> > which UNIX rm doesn't do.  Maybe the way this is implemented is a
> > little confusing, although I just read the man page and it seemed
> > pretty clear to me.
> 
>   um, wrong.

I don't know what part of my comment here you consider "wrong".  I've
re-read it and I believe everything I said is correct.

> > If you don't use glob patterns (or more specifically if you let the
> > shell handle glob patterns, which is how I always do it) then there
> > is really nothing bizarre about "git rm".  Maybe you could be more
> > precise in your criticism.
> 
> ok, fine, let me explain why this command is a nightmarish
> monstrosity. as i now understand, if i use an escaped wildcard
> pattern, "git rm" will *automatically* (with no further guidance from
> me, and no warning), operate recursively. so if, in the kernel source
> tree, i ran:
> 
>   $ git rm \*.c

Yes, this is what I said: "IF YOU DON'T USE GLOB PATTERNS (or more
specifically if you let the shell handle glob patterns ...) then there
is nothing bizarre about "git rm"" (emphasis added).

In this example you ARE sending glob patterns to Git, because you're
escaping them from the shell.  Hence, you might consider the behavior
bizarre, at least until you grok it fully.

If you want to avoid this, simply use normal shell globbing and don't
ask Git to do the globbing for you.  Then it behaves exactly as normal
UNIX rm, including with the '-r' option, and is very simple.

> so if i wanted git to remove, say, all files named "Makefile*" from
> everywhere in the linux kernel source tree, the (dry run) command
> would be:
> 
>   $ git rm -n Makefile\*
> 
> is that it? let's try that:
> 
>   $ git rm -n Makefile\*
>   rm 'Makefile'
>   $
> 
> oops.

Globbing in "git rm" matches on the FULL PATH, not just the file name. 
So, if you have a list of Makefiles in your repository like:

  Makefile
  foo/Makefile
  bar/Makefile

Then 'Makefile*' only matches the first one, since 'Makefile*' doesn't
match 'foo/Makefile' or 'bar/Makefile'.

If you you worry that '*Makefile' will match things you don't want to
match, you'll have to use:

  git rm -n Makefile '*/Makefile'

Personally I don't use Git's magical globbing capabilities, and use "git
rm" as if it were UNIX rm.  So in your request above I'd use:

   git rm $(find . -name Makefile)

which I find simpler.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 14:32                 ` Paul Smith
@ 2017-10-08 18:40                   ` Theodore Ts'o
  2017-10-08 19:44                     ` Robert P. J. Day
  0 siblings, 1 reply; 29+ messages in thread
From: Theodore Ts'o @ 2017-10-08 18:40 UTC (permalink / raw)
  To: Paul Smith; +Cc: Robert P. J. Day, Git Mailing list

On Sun, Oct 08, 2017 at 10:32:40AM -0400, Paul Smith wrote:
> Personally I don't use Git's magical globbing capabilities, and use "git
> rm" as if it were UNIX rm.  So in your request above I'd use:
> 
>    git rm $(find . -name Makefile)
> 
> which I find simpler.

I have to agree that git's magical globbing capabilities
are... strange.  (And apologies to Robert for my earlier post; I
didn't understand what he was complaining about.)  I don't use it
either, although I tend to use:

    find <find args> | xargs git rm

myself.

One thing which is interesting is that not only is the git's magical
globbing capabilities have somewhat unusual semantics, the how
globbing is done in .gitignore entries are completely different.

Shrug.  I put this in the same category as "tabs are significant in
Makefile's", "whitespace is significant in python", and "the many
varied different behaviours and uses of 'git reset'".

They are all idiosyncrancies of semantics of various highly popular
tools (which being highly popular, would make changing the details
quite difficult due to backwards compatibility concerns, even if we
wanted to change them).

						- Ted



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 18:40                   ` Theodore Ts'o
@ 2017-10-08 19:44                     ` Robert P. J. Day
  2017-10-08 20:42                       ` Theodore Ts'o
  0 siblings, 1 reply; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-08 19:44 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Paul Smith, Git Mailing list

On Sun, 8 Oct 2017, Theodore Ts'o wrote:

> On Sun, Oct 08, 2017 at 10:32:40AM -0400, Paul Smith wrote:
> > Personally I don't use Git's magical globbing capabilities, and
> > use "git rm" as if it were UNIX rm.  So in your request above I'd
> > use:
> >
> >    git rm $(find . -name Makefile)
> >
> > which I find simpler.
>
> I have to agree that git's magical globbing capabilities are...
> strange.  (And apologies to Robert for my earlier post; I didn't
> understand what he was complaining about.)  I don't use it either,
> although I tend to use:
>
>     find <find args> | xargs git rm
>
> myself.

  that's what i would have normally used until i learned about git's
magical globbing capabilities, and i'm going to go back to using it,
because git's magical globbing capabilities now scare me.

> One thing which is interesting is that not only is the git's magical
> globbing capabilities have somewhat unusual semantics, the how
> globbing is done in .gitignore entries are completely different.

  i know ... it would have made way more sense to try to be
consistent. oh, well, live and learn. at least now i'm aware of the
weirdness.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 19:44                     ` Robert P. J. Day
@ 2017-10-08 20:42                       ` Theodore Ts'o
  2017-10-09 17:52                         ` Jeff King
  0 siblings, 1 reply; 29+ messages in thread
From: Theodore Ts'o @ 2017-10-08 20:42 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Paul Smith, Git Mailing list

On Sun, Oct 08, 2017 at 03:44:14PM -0400, Robert P. J. Day wrote:
> >
> >     find <find args> | xargs git rm
> >
> > myself.
> 
>   that's what i would have normally used until i learned about git's
> magical globbing capabilities, and i'm going to go back to using it,
> because git's magical globbing capabilities now scare me.

Hmm, I wonder if the reason why git's magically globbing capabilities
even exist at all is for those poor benighted souls on Windows, for
which their shell (and associated utilities) doesn't have advanced
tools like "find" and "xargs"....

				- Ted

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 20:42                       ` Theodore Ts'o
@ 2017-10-09 17:52                         ` Jeff King
  2017-10-10  8:36                           ` Robert P. J. Day
  0 siblings, 1 reply; 29+ messages in thread
From: Jeff King @ 2017-10-09 17:52 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Robert P. J. Day, Paul Smith, Git Mailing list

On Sun, Oct 08, 2017 at 04:42:27PM -0400, Theodore Ts'o wrote:

> On Sun, Oct 08, 2017 at 03:44:14PM -0400, Robert P. J. Day wrote:
> > >
> > >     find <find args> | xargs git rm
> > >
> > > myself.
> > 
> >   that's what i would have normally used until i learned about git's
> > magical globbing capabilities, and i'm going to go back to using it,
> > because git's magical globbing capabilities now scare me.
> 
> Hmm, I wonder if the reason why git's magically globbing capabilities
> even exist at all is for those poor benighted souls on Windows, for
> which their shell (and associated utilities) doesn't have advanced
> tools like "find" and "xargs"....

One benefit of globbing with Git is that it restricts the matches only
to tracked files. That matters a lot when you have a very broad glob
(e.g., like you might use with "git grep") because it avoids looking at
cruft like generated files (or even inside .git).

-Peff

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-09 17:52                         ` Jeff King
@ 2017-10-10  8:36                           ` Robert P. J. Day
  2017-10-10  8:58                             ` Junio C Hamano
  2017-10-10 12:19                             ` Paul Smith
  0 siblings, 2 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-10  8:36 UTC (permalink / raw)
  To: Jeff King; +Cc: Theodore Ts'o, Paul Smith, Git Mailing list

On Mon, 9 Oct 2017, Jeff King wrote:

> On Sun, Oct 08, 2017 at 04:42:27PM -0400, Theodore Ts'o wrote:
>
> > On Sun, Oct 08, 2017 at 03:44:14PM -0400, Robert P. J. Day wrote:
> > > >
> > > >     find <find args> | xargs git rm
> > > >
> > > > myself.
> > >
> > >   that's what i would have normally used until i learned about
> > > git's magical globbing capabilities, and i'm going to go back to
> > > using it, because git's magical globbing capabilities now scare
> > > me.
> >
> > Hmm, I wonder if the reason why git's magically globbing
> > capabilities even exist at all is for those poor benighted souls
> > on Windows, for which their shell (and associated utilities)
> > doesn't have advanced tools like "find" and "xargs"....
>
> One benefit of globbing with Git is that it restricts the matches
> only to tracked files. That matters a lot when you have a very broad
> glob (e.g., like you might use with "git grep") because it avoids
> looking at cruft like generated files (or even inside .git).

  ah, now *that* is a compelling rationale that justifies the
underlying weirdness. but it still doesn't explain the different
behaviour between:

  $ git rm -n 'Makefile*'
  $ git rm -n '*Makefile'

in the linux kernel source tree, the first form matches only the
single, top-level Makefile, while the second form gets *all* of them
recursively, even though those globs should be equivalent in terms of
matching all files named "Makefile".

  am i misunderstanding something?

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-10  8:36                           ` Robert P. J. Day
@ 2017-10-10  8:58                             ` Junio C Hamano
  2017-10-10 12:19                             ` Paul Smith
  1 sibling, 0 replies; 29+ messages in thread
From: Junio C Hamano @ 2017-10-10  8:58 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Jeff King, Theodore Ts'o, Paul Smith, Git Mailing list

"Robert P. J. Day" <rpjday@crashcourse.ca> writes:

> underlying weirdness. but it still doesn't explain the different
> behaviour between:
>
>   $ git rm -n 'Makefile*'
>   $ git rm -n '*Makefile'
>
> in the linux kernel source tree, the first form matches only the
> single, top-level Makefile, while the second form gets *all* of them
> recursively, even though those globs should be equivalent in terms of
> matching all files named "Makefile".
>
>   am i misunderstanding something?

We are matching what Git cares/knows about aka "the paths in the
index" to pathspec patterns.

What are these paths in the index?  In Linux kernel sources, there
are quite a many but here are examples that are enough to explain
the above:

	Makefile
        COPYING
	fs/Makefile
	fs/ext4/Makefile

Which one of these four match patterh "Makefile*", which is "the
first letter is 'M', the second letter is 'a', ....,, the eighth
letter is 'e', and anything else can follow to the end"?  Yes, only
the first one.

Which one of these four match pattern "*Makefile", then?  "Anything
can appear as leading substring, but then 'M', 'a', 'k', ..., and
finally 'e' must appear at the end"?

Note that these "start from the paths in the index that match the
pathspec patterns" have nothing to do with "recursive".  It happens
way before we decide to go recursive (or not).

We are not going down recursively from the paths in the index that
are matched by pathspec patterns with the above two "git rm"
requests (because there is no "-r" there), but even if we were,
because these three Makefile files are not directories, there is
nothing to remove recursively underneath them.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-08 11:56                   ` Robert P. J. Day
  2017-10-08 12:23                     ` Martin Ågren
  2017-10-08 12:39                     ` René Scharfe
@ 2017-10-10 11:52                     ` Heiko Voigt
  2017-10-11  8:31                       ` Robert P. J. Day
  2 siblings, 1 reply; 29+ messages in thread
From: Heiko Voigt @ 2017-10-10 11:52 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Junio C Hamano, Paul Smith, Git Mailing list

On Sun, Oct 08, 2017 at 07:56:20AM -0400, Robert P. J. Day wrote:
>   but as i asked in my earlier post, if i wanted to remove *all* files
> with names of "Makefile*", why can't i use:
> 
>   $ git rm 'Makefile*'
> 
> just as i used:
> 
>   $ git rm '*.c'
> 
> are those not both acceptable fileglobs? why does the former clearly
> only match the top-level Makefile, and refuse to cross directory
> boundaries?

Maybe think about it this way: The only difference between git's
globbing and the default shell globbing is that the '/' in a path has a
special meaning. The shells expansion stops at a '/' but git does not.

So with *.c the shell matches: blabla.c, blub.c, ...  but not
subdir/bla.c, subdir/blub.c, ... since it only considers files in the
current directory. A little different for Makefile* that will also match
Makefile.bla, Makefile/bla or Makefile_bla/blub in shell but not
subdir/Makefile or bla.Makefile. Basically anything directly in *this*
directory that *starts* with 'Makefile'.

Git on the other hand does not consider '/' to be special. So *.c
matches all of the path above: bla.c, blub.c, subdir/bla.c,
subdir/blub.c. Basically any file below the current directory with a
path that ends in '.c'. With Makefile* it is the opposite: Every file
below the current directory that *starts* with 'Makefile'. So
Makefile.bla, Makefile/bla, ... but also not subdir/Makefile or
bla.Makefile.

Maybe that helps...

Cheers Heiko


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-10  8:36                           ` Robert P. J. Day
  2017-10-10  8:58                             ` Junio C Hamano
@ 2017-10-10 12:19                             ` Paul Smith
  2017-10-10 19:44                               ` Robert P. J. Day
  1 sibling, 1 reply; 29+ messages in thread
From: Paul Smith @ 2017-10-10 12:19 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Git Mailing list

On Tue, 2017-10-10 at 04:36 -0400, Robert P. J. Day wrote:
>   ah, now *that* is a compelling rationale that justifies the
> underlying weirdness. but it still doesn't explain the different
> behaviour between:
> 
>   $ git rm -n 'Makefile*'
>   $ git rm -n '*Makefile'

I explained that behavior in the email up-thread from this reply:

> Globbing in "git rm" matches on the FULL PATH, not just the file name. 
> So, if you have a list of Makefiles in your repository like:
> 
>   Makefile
>   foo/Makefile
>   bar/Makefile
> 
> Then 'Makefile*' only matches the first one, since 'Makefile*' doesn't
> match 'foo/Makefile' or 'bar/Makefile'.
>
> If you you worry that '*Makefile' will match things you don't want to
> match, you'll have to use:
> 
>   git rm -n Makefile '*/Makefile'


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-10 12:19                             ` Paul Smith
@ 2017-10-10 19:44                               ` Robert P. J. Day
  0 siblings, 0 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-10 19:44 UTC (permalink / raw)
  To: Paul Smith; +Cc: Git Mailing list

[-- Attachment #1: Type: text/plain, Size: 884 bytes --]

On Tue, 10 Oct 2017, Paul Smith wrote:

> On Tue, 2017-10-10 at 04:36 -0400, Robert P. J. Day wrote:
> >   ah, now *that* is a compelling rationale that justifies the
> > underlying weirdness. but it still doesn't explain the different
> > behaviour between:
> >
> >   $ git rm -n 'Makefile*'
> >   $ git rm -n '*Makefile'
>
> I explained that behavior in the email up-thread from this reply:

  yup, sorry i missed it. man, it's been an educational thread.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: "git rm" seems to do recursive removal even without "-r"
  2017-10-10 11:52                     ` Heiko Voigt
@ 2017-10-11  8:31                       ` Robert P. J. Day
  0 siblings, 0 replies; 29+ messages in thread
From: Robert P. J. Day @ 2017-10-11  8:31 UTC (permalink / raw)
  To: Heiko Voigt; +Cc: Junio C Hamano, Paul Smith, Git Mailing list

On Tue, 10 Oct 2017, Heiko Voigt wrote:

> On Sun, Oct 08, 2017 at 07:56:20AM -0400, Robert P. J. Day wrote:
> >   but as i asked in my earlier post, if i wanted to remove *all* files
> > with names of "Makefile*", why can't i use:
> >
> >   $ git rm 'Makefile*'
> >
> > just as i used:
> >
> >   $ git rm '*.c'
> >
> > are those not both acceptable fileglobs? why does the former
> > clearly only match the top-level Makefile, and refuse to cross
> > directory boundaries?
>
> Maybe think about it this way: The only difference between git's
> globbing and the default shell globbing is that the '/' in a path
> has a special meaning. The shells expansion stops at a '/' but git
> does not.
>
> So with *.c the shell matches: blabla.c, blub.c, ...  but not
> subdir/bla.c, subdir/blub.c, ... since it only considers files in
> the current directory. A little different for Makefile* that will
> also match Makefile.bla, Makefile/bla or Makefile_bla/blub in shell
> but not subdir/Makefile or bla.Makefile. Basically anything directly
> in *this* directory that *starts* with 'Makefile'.
>
> Git on the other hand does not consider '/' to be special. So *.c
> matches all of the path above: bla.c, blub.c, subdir/bla.c,
> subdir/blub.c. Basically any file below the current directory with a
> path that ends in '.c'. With Makefile* it is the opposite: Every
> file below the current directory that *starts* with 'Makefile'. So
> Makefile.bla, Makefile/bla, ... but also not subdir/Makefile or
> bla.Makefile.

   ok, i believe i finally appreciate what is happening here, and
perhaps my first contribution will be a minor addition to the "git-rm"
man page to introduce a couple examples explaining these intricacies,
since they're not immediately obvious. i'll put something together and
submit it to the list. thank you all for your patience in explaining
this.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                        http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, back to index

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-07 18:39 "git rm" seems to do recursive removal even without "-r" Robert P. J. Day
2017-10-07 19:04 ` Todd Zullinger
2017-10-07 19:12   ` Robert P. J. Day
2017-10-07 19:29     ` Jeff King
2017-10-07 19:32       ` Robert P. J. Day
2017-10-07 19:38         ` Jeff King
2017-10-07 19:43           ` Robert P. J. Day
2017-10-07 21:05             ` Theodore Ts'o
2017-10-07 21:40               ` Robert P. J. Day
2017-10-07 21:44             ` Paul Smith
2017-10-07 21:55               ` Robert P. J. Day
2017-10-08  4:20                 ` Junio C Hamano
2017-10-08  9:07                   ` Robert P. J. Day
2017-10-08 11:37                     ` Kevin Daudt
2017-10-08 11:56                   ` Robert P. J. Day
2017-10-08 12:23                     ` Martin Ågren
2017-10-08 12:39                     ` René Scharfe
2017-10-08 12:45                       ` Robert P. J. Day
2017-10-10 11:52                     ` Heiko Voigt
2017-10-11  8:31                       ` Robert P. J. Day
2017-10-08 14:32                 ` Paul Smith
2017-10-08 18:40                   ` Theodore Ts'o
2017-10-08 19:44                     ` Robert P. J. Day
2017-10-08 20:42                       ` Theodore Ts'o
2017-10-09 17:52                         ` Jeff King
2017-10-10  8:36                           ` Robert P. J. Day
2017-10-10  8:58                             ` Junio C Hamano
2017-10-10 12:19                             ` Paul Smith
2017-10-10 19:44                               ` Robert P. J. Day

git@vger.kernel.org mailing list mirror (one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/
       or Tor2web: https://www.tor2web.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox