git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [RFC PATCH] submodule: make '^/' work like '../' but with an absolute path

From
Jacob Keller <jacob.keller@gmail.com>
Date
Oct 25, 2026, 23:11 UTC
Message-ID
<CA+P7+xo8J_+3QECoGHnN1AxXPpjaKaHp3VoN9EEcyhZ+Q1fzew@mail.gmail.com>
In-Reply-To
<20261025212517.479922-1-lightofmysoul@gmail.com>

On Sun, Oct 25, 2026 at 2:25 PM Stanislav Aleksandrov <lightofmysoul@gmail.com> wrote:

Show 38 quoted lines
>
> On Sun, Oct 25, 2026 at 12:42 PM Jacob Keller
> <jacob.keller@gmail.com> wrote:
> > On Tue, Sep 29, 2026 at 11:51 AM Stanislav Aleksandrov
> > <lightofmysoul@gmail.com> wrote:
> >> - Why not url.<base>.insteadOf? It has to be set up on every clone;
> >>   .gitmodules cannot carry it.
> >
> > Could .gitmodules be extended to carry this information?
>
> Not as a rewrite rule. A rule maps one fixed prefix to another, and
> .gitmodules is the same for everyone, so it can't send one person over
> https and another over ssh with their own host alias. What differs per
> clone is the superproject's remote URL, and that's what "../" and "^/"
> resolve against.
>
> We could add a separate "same server as the superproject" key next to
> an absolute URL and then Git would ignore the host written in that
> URL, but that would be really confusing.
>
> >> - Compatibility: a local "^/..." path needs a "^" directory in the
> >>   superproject and protocol.file.allow=always, and "git submodule
> >>   add" refuses it.
> >
> > What do you mean here by "refuses it" Is this character already
> > refused? I.e. "^" isn't considered a valid directory, which is why its
> > suitable for converting to a special meaning?
>
> No, "^" is a valid directory name, and today "^/org/lib.git" means a
> repository in a "^" directory of the superproject. By "refuses" I
> meant that "git submodule add" rejects it, as it does "foo/lib.git":
>
>   fatal: repo URL: '^/org/lib.git' must be absolute or begin with ./|../
>
> So such a URL has to be written into .gitmodules by hand or with "git
> submodule set-url", and since 2.38.1 it can't be cloned without
> protocol.file.allow=always. It is possible, just very unlikely.
>

I see. Because protocol.file.allow is set to "user" by default, submodules can't use file-based URLs that get interpreted as local paths so only very weird setups could be using "^" in their current configuration. Makes sense. The likelihood of breaking someone would be very low then.

Show 7 quoted lines
> > The ultimate goal would be to allow users to specify what protocol
> > they want to operate on.
>
> Relative URLs already do that: a superproject cloned over ssh gets its
> "../" submodules over ssh too. The problem is that they also follow
> where the superproject lives.
>

Right. I guess it is more that using relative URLs breaks forks but using absolute paths forces protocol on everyone so it is not a great fallback.

Show 9 quoted lines
> > I guess "insteadOf" even in the .gitmodules wouldn't work because you
> > wouldn't want to apply that to everyone. The issue seems to be caused
> > because of the URLs on Gitlab changing such that relative paths don't
> > work anymore?
>
> The URLs don't change. Forks are the problem. A fork lives in another
> namespace, and on GitLab often at a different depth, because groups
> can be nested.
>

Right. The "relative" URL of the fork just doesn't work unless the subproject itself is forked.

Show 22 quoted lines
> > Does doing something like "../../" work to allow the subproject to
> > find the root from a relative path? Or does the current logic not
> > support multiple ".."?
>
> Multiple ".." work, but the count has to match how deep the
> superproject is. Let's say the upstream is https://gitlab.com/org/super.git
> and lib is https://gitlab.com/org/lib.git:
>
>   - "../lib.git" gives me/lib.git for a fork at me/super.git, which
>     only exists if lib was forked too.
>   - "../../org/lib.git" works for me/super.git, but gives
>     group/org/lib.git for a fork at group/team/super.git.
>   - "../../../org/lib.git" works for group/team/super.git, but for
>     me/super.git it climbs past the root and eats the host:
>     https://org/lib.git.
>
> "^/org/lib.git" gives https://gitlab.com/org/lib.git for all of them,
> or git@gitlab.com:org/lib.git if the superproject was cloned over ssh.
>
> On GitHub every repository is two levels deep, so "../../org/lib.git"
> works for everyone. GitLab and plain SSH servers have no fixed
> depth.

Yep, that lays out the full reasoning for why you'd want this. Forking the main repository could end up with broken submodule URLs unless you *also* fork the submodules. Depending on your project you may (or may not) want to do that, so having the option to use ^/ is good. Of course using "^/" would mean that forking both super and subproject would potentially break, until/unless you update your fork to point to the new fork URL. I guess that is more semantically correct, your fork of a super project woudl only change once you officially tell it to move to the appropriate fork.

I think the concept does make sense, if being driven somewhat by a specific forge decision. Of course this could be useful on other forges in the future.

Previous: Stanislav AleksandrovNext: Stanislav Aleksandrov
Message 4 of 8 in “submodule: make '^/' work like '../' but with an absolute path”
  1. submodule: make '^/' work like '../' but with an absolute pathStanislav Aleksandrov, Sep 29, 2026
  2. Jacob KellerOct 25, 2026
  3. Stanislav AleksandrovOct 25, 2026
  4. Jacob KellerOct 25, 2026
  5. Stanislav AleksandrovOct 30, 2026
  6. Junio C HamanoOct 27, 2026
  7. Stanislav AleksandrovOct 30, 2026
  8. Junio C HamanoOct 31, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.