Home > front end >  How to escape `--' in git submodule name?
How to escape `--' in git submodule name?

Time:07-11

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.

  •  Tags:  
  • git
  • Related