git-filter-branch with --index-filter : strange bash error ( ! : event not found)
-
03-07-2021 - |
Domanda
I am using the answer to this question to strip a clone of a repository to a list of files I want to keep in a spin off of this project. Say I want to strip all but directory src/main
and its sub-directories. Because I will have multiple files and directories, I use --index-filter
instead of --subdirectory-filter
.
I thought the following should work:
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩
src/!(main)" --prune-empty -- --all
But all I get is
-bash: !: event not found
I tried all sorts of different paths instead of src/!(main)
. I always get exactly that error message. It seems to be a bash problem, because that line also doesn't enter my command line history?
That is to say, if I have top level files A
, and B
, and subdirectory C/D
, how can I remove all but these three things?
Soluzione
The ! is the issue, since it is used for command history recall. Inside quotes, putting a backslash in front does not help either, so the \!
must be outside quotes. Can be illustrated using a few examples with echo:
/home/user1> echo "src/!(main)"
-bash: !: event not found
/home/user1> echo "src/\!(main)"
src/\!(main)
/home/user1> echo "src/"\!"(main)"
src/!(main)
Altri suggerimenti
To answer the the actual question added in the clarification: you're trying to use bash's extglob to remove everything in src
but main
in a git index-filter
. This doesn't work because the index-filter command is not executed by your shell, but by sh
via eval
(see /usr/lib/git-core/git-filter-branch:327
).
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch $(ls -xd src/!(main))" --prune-empty -- --all
The exclamation point is used in Bash's syntax to do history expansion, which is what causes the confusion. You must escape it using backslash or single quotes:
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ↩
src/\!(main)" --prune-empty -- --all