Although we definitely support and encourage use of multi-level branch
names, we have never conciously tried to give support for multi-level
remote names. Currently, they are allowed, but there is no evidence that
they are commonly used.

Now, they do provide a source of problems when trying to expand the
"$nick/$name" shorthand notation (where $nick matches a remote name)
into a full refname. Consider the shorthand "foo/bar/baz": Does this
parse as $nick = foo, $name = bar/baz, or $nick = foo/bar, $name = baz?

Since we need to be unambiguous about these things, we hereby declare
that a remote name shall never contain a '/' character, and that the
only correct way to parse "foo/bar/baz" is $nick = foo, $name = bar/baz.

This patch teaches 'git remote' to reject remote names with slashes,
and adds tests verifying this.

Signed-off-by: Johan Herland <>
 builtin/remote.c  |  4 ++--
 t/ | 12 ++++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 5e54d36..6e7369d 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -195,7 +195,7 @@ static int add(int argc, const char **argv)
                die(_("remote %s already exists."), name);
        strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
-       if (!valid_fetch_refspec(buf2.buf))
+       if (!valid_fetch_refspec(buf2.buf) || strchr(name, '/'))
                die(_("'%s' is not a valid remote name"), name);
        strbuf_addf(&buf, "remote.%s.url", name);
@@ -646,7 +646,7 @@ static int mv(int argc, const char **argv)
                die(_("remote %s already exists."),;
        strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test",;
-       if (!valid_fetch_refspec(buf.buf))
+       if (!valid_fetch_refspec(buf.buf) || strchr(, '/'))
                die(_("'%s' is not a valid remote name"),;
diff --git a/t/ b/t/
index dd10ff0..f7098fe 100755
--- a/t/
+++ b/t/
@@ -621,6 +621,12 @@ test_expect_success 'reject adding remote with an invalid 
name' '
+test_expect_success 'reject adding remote with slash in name' '
+       test_must_fail git remote add multi/level .
 # The first three test if the tracking branches are properly renamed,
 # the last two ones check if the config is updated.
@@ -668,6 +674,12 @@ test_expect_success 'rename a remote with name prefix of 
other remote' '
+test_expect_success 'rename a remote with slash in name' '
+       test_must_fail git remote rename upstream up/stream
 cat > remotes_origin << EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to
More majordomo info at

Reply via email to