list mirror (unofficial, one of many)
 help / color / Atom feed
From: Junio C Hamano <>
To: "Robert P. J. Day" <>
Cc: Paul Smith <>,
	Git Mailing list <>
Subject: Re: "git rm" seems to do recursive removal even without "-r"
Date: Sun, 08 Oct 2017 13:20:13 +0900
Message-ID: <> (raw)
In-Reply-To: <alpine.LFD.2.21.1710071749240.16818@localhost.localdomain> (Robert P. J. Day's message of "Sat, 7 Oct 2017 17:55:48 -0400 (EDT)")

"Robert P. J. Day" <> 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

Hope this clarifies and helps.

  reply index

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-07 18:39 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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information:

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \ \ \ \ \ \

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Example config snippet for mirrors

Newsgroups are available over NNTP:

 note: .onion URLs require Tor:

AGPL code for this site: git clone