On Sun, 8 Oct 2017, Junio C Hamano wrote: > "Robert P. J. Day" <rpjday@xxxxxxxxxxxxxx> 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 ========================================================================