I added a git submodule with the following command:
git submodule add https://github.com/spaceship-prompt/spaceship-prompt.git --depth=1
This command mistook --depth=1
as a module name, rather than the repo depth. When I run git submodule
I get:
a5d55898822e75cb34ee1c3cefe52822c820c220 zshrc/zsh_prompts/--depth=1 (v3.11.2-386-ga5d5589)
Now I want to remove this submodule. Since I have not run git submodule init
, I can run git rm -f "--depth=1"
to remove it, but get the following error:
error: unknown option `depth=1/'
usage: git rm [<options>] [--] <file>...
-n, --dry-run dry run
-q, --quiet do not list removed files
--cached only remove from the index
-f, --force override the up-to-date check
-r allow recursive removal
--ignore-unmatch exit with a zero status even if nothing matched
--pathspec-from-file <file>
read pathspec from file
--pathspec-file-nul with --pathspec-from-file, pathspec elements are separated with NUL character
How do I escape the --
in the submodule name and remove it?
CodePudding user response:
You have discovered the reason that --
, the "end of options" marker, exists in the first place.
Consider the more general problem of removing a file named -f
. Running:
rm -f
doesn't work, because -f
is a flag to rm
. One solution is:
rm ./-f
which does work as it names the same file, but doesn't start with -
and hence does not resemble the -f
flag. (This also works for your git rm
issue.)
In some cases, however, there's no "alternate name that means the same thing". For these cases, we'd like to have:
<cmd> <option> <argument>
be treated as the command with the option and argument, but:
<cmd> <argument-that-resembles-option> <argument>
be treated as the command, but with two arguments. If the command follows one common convention, we may be able to reverse the two arguments:
rm foo -f
for instance may treat the -f
as a file name. But if it follows a different common convention, the -f
is still an option.
So, enter the --
option, which means everything after this is not an option after all. We simply write:
<cmd> -- <argument-that-resembles-option> <argument>
For instance:
rm -- -f
or:
git rm -- --depth=1
The --
tells the command that subsequent arguments are not options even if they look like options.
This works well with other commands, where:
git checkout main --
means check out the branch named main
while:
git checkout -- main
means discard my changes to the file named main in the current branch.
It's a good idea to learn about --
and get in the habit of using it, even when it's clearly not required, just so that you will use --
when it is required. (Or, in the case of git checkout
, to switch to the two commands git switch
and git restore
, but that's another matter entirely.