git-rm fu
- From
Jon Loeliger <jdl@jdl.com>
- Date
- Apr 13, 2008, 20:44 UTC
- Message-ID
- <E1Jl949-0000yh-M1@jdl.com>
Given:
$ git init Initialized empty Git repository in .git/ $ echo one >> git-foo.sh $ mkdir subdir $ echo two >> subdir/git-foo.sh $ mkdir subdir/snizzle $ echo three >> subdir/snizzle/git-foo.sh $ git add . $ git commit -m"All quiet on the western front." Created initial commit 15fe70d: All quiet on the western front. 3 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 git-foo.sh create mode 100644 subdir/git-foo.sh create mode 100644 subdir/snizzle/git-foo.sh
The "git rm" manual's second example says:
git-rm -f git-*.sh
Remove all git-*.sh scripts that are in the index. 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.It is not true that this command will remove all git-*.sh scripts that are in the index. Here are three:
$ git ls-files
git-foo.sh
subdir/git-foo.sh
subdir/snizzle/git-foo.shUsing -f on this command is a red herring. Using -f or -n doesn't matter, and since we want to do more than one command here, I'm just going to show it all using -n:
The effect of the command is to match just one file at the top level:
$ git rm -n git-*.sh
rm 'git-foo.sh'Furthermore, there is an implication in the wording of the second example that suggests that if you had let git expand the file glob, the subdir/git-foo.sh file would have been removed.
Also not true:
$ git rm -n git-\*.sh
rm 'git-foo.sh'To actually get the behavior of "removing all git-*.sh scripts from the index", you have to prefix a file glob at the front of the paths to match directories too:
$ git rm -n \*git-\*.sh
rm 'git-foo.sh'
rm 'subdir/git-foo.sh'
rm 'subdir/snizzle/git-foo.sh'But then, using any of:
\*git-\*.sh
\*git-*.sh
*git-\*.shall effectively *will* match subdir/git-foo.sh:
$ git rm -n \*git-*.sh
rm 'git-foo.sh'
rm 'subdir/git-foo.sh'
rm 'subdir/snizzle/git-foo.sh' $ git rm -n *git-\*.sh
rm 'git-foo.sh'
rm 'subdir/git-foo.sh'
rm 'subdir/snizzle/git-foo.sh'So it seems that the two parts discussed in the second example are really unrelated.
It seems like "git rm d2/*" should remove all of d2's files without trying to recursively remove any subdirectories, but it won't:
$ git rm -n d2/*
fatal: not removing 'd2/two' recursively without -rBut then using -r force d2/two/ to be removed as well:
$ git rm -n d2/\*
rm 'd2/two/xyzzy'
rm 'd2/x'
rm 'd2/y'
rm 'd2/z'There's no real way to say "just the files in d2/".
(Yeah, sure, I could have said "git rm d2/\?", but that wouldn't work if d2/xyzzy existed too. :-))
jdl