How to pull from a remote name which begin with a dash

263 views Asked by At

In git, it is possible to handle a remote name with - character star.

For example, we can add a remote which begins with -, update it by just using the option -- in the git command (-- separate between command option and the remote name).

But it doesn't work on :

git pull -- "-myremotename" "master"

And, I get this error message :

error: unknown switch `y'
usage: git fetch [<options>] [<repository> [<refspec>...]]

I think that -- option doesn't work in git pull, because pull is a combination of git fetch followed by git merge, and -- isn't used when making this 2 commands.

Any idea to fix it ?

1

There are 1 answers

1
hakre On

Any idea to fix it ?

Prefix the remote name with the word safe

$ git remote rename {,safe}-myremotename

You can then use it again

$ git pull safe-myremotename 
Successfully rebased and updated refs/heads/develop

As remote names land in the file-system and also are prone to injection as your question shows, please consider the following:

  • Use only characters from the 3.282 Portable Filename Character Set

    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    0 1 2 3 4 5 6 7 8 9 . _ -
    
  • Do not use the dash - as first character. (ref)

  • Do not use any of the digits 0-9 and letters a-f/A-F within the remote name only (if the name is longer than three characters). Otherwise a remote name may become refused by git(1) in the future of your repository. (ref)

And additional and more in general:

  • Consider to not start names with a digit 0-9.
  • Consider to not start nor end names with punctuation, here ., _ or -.
  • Consider to use only one case, either lower a-z or upper A-Z.
  • Consider to keep the remote name as long as needed while as short as possible, not shorter than three letters. Eight characters is normally a good maximum.

And thanks for asking. It is exactly as you wrote that git-pull(1) allows to specify the remote name after -- while that in the git-fetch(1) invocation by it, the remote name is passed verbatim into the arguments list.

It does not look like an ordinary injection that allows to get ownage of the whole bakery. The only thing that can be injected to git-fetch(1) is a single parameter by the configured remote.<name>.

E.g. with a single remote named --all we can send git-pull(1) (and, via), git-fetch(1) into child recursion. That is fun but also spams tty

Example

Name of the remote: --all

Process tree of git pull -- --all (limited to 6 lines):

 121540 Ss+  00:00:00 -/bin/sh
 122011 T    00:00:00  \_ git pull -- --all
 122012 T    00:00:00      \_ /usr/lib/git-core/git fetch --update-head-ok --all
 122023 T    00:00:00          \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --update-head-ok --all
 122034 T    00:00:00              \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --update-head-ok --all
 122045 T    00:00:00                  \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --update-head-ok --all

Does git-fetch(1) tricks itself here already? Sort of, but only if --jobs=1. With --jobs=2 or higher than 2, git-fetch(2) does process the option more sequentially and not all-over and again and again. But only if there are at least two remotes.

 121540 Ss+  00:00:00 -/bin/sh
 127528 T    00:00:00  \_ git fetch --all
 127539 T    00:00:00      \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127550 T    00:00:00          \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127561 T    00:00:00              \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127572 T    00:00:00                  \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127583 T    00:00:00                      \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127594 T    00:00:00                          \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127605 T    00:00:00                              \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all
 127616 T    00:00:00                                  \_ /usr/lib/git-core/git fetch --append --no-auto-gc --no-write-commit-graph --all

Well, looks like. git-fetch --all has no sanity check to detect if it is re-entrant for the same remote name nor seems to have an option with its own argument to denote the remote (either by name or URL) which could prevent that.

(git version 2.25.1)