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

Re: git aliases and GIT_PREFIX

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Nov 4, 2021, 00:02 UTC
Message-ID
<nycvar.QRO.7.76.6.2111040047540.56@tvgsbejvaqbjf.bet>
In-Reply-To
<20211102172644.cnsro5p3m6o6b6po@gmail.com>
Hi Federico,
On Tue, 2 Nov 2021, Federico Kircheis wrote:
Show 53 quoted lines
> On Tue, Nov 02, 2021 at 03:26:05PM +0100, Johannes Schindelin wrote:
> >
> >On Thu, 28 Oct 2021, Federico Kircheis wrote:
> >
> > > today I reported what I believed to be a bug on
> > >
> > >  https://github.com/git-for-windows/git/issues/3496
> > >
> > > and learned about GIT_DIR when working with aliases and git worktree.
> > >
> > > It's annoying that GIT_DIR it is defined only if (as far as I've
> > > understood)
> > > working from a worktrees or submodule, as it does not seem to be related
> > > to
> > > those type of repositories.
> >
> >To clarify: `GIT_DIR` is set when executing an alias in a worktree other
> >than the primary one (and probably also in submodules), but not when
> >executing in a primary worktree.
> >
> > > This is also irritating because apparently working aliases breaks when
> > > being
> > > executed from those repositories.
> >
> >To clarify: an alias that wants to switch to a different repository and
> >execute Git commands there works well in a primary worktree. But when you
> >switch to a different repository while executing an alias from a secondary
> >worktree, it will fail because of `GIT_DIR` having been set.
> >
> > > I believe it would be better if GIT_DIR it's either always set or never
> > > (could someone enlighten me why the variable is needed in first place?).
>
> Yes, sorry if I was not clear, your clarification are what I meant to say.
>
> >The fact that `GIT_DIR` is not set when calling an alias in a primary
> >worktree suggests that the behavior in secondary worktrees is not by
> >design. We should therefore be able to stop setting it there.
> >
> >The question is: what code is responsible for setting it only in some
> >circumstances but not others?
> >
> >Federico, do you have any experience in debugging C code? If so, it would
> >be good if you could take a crack at investigating this.
> >
> >Ciao,
> >Johannes
>
> Yes, I have some experience, but never looked at the git codebase.
>
> On GitHub (https://github.com/git-for-windows/git/issues/3496) there is
> already an hint where those variables are set:
>
>   https://github.com/git/git/blob/v2.33.1/git.c#L354

Well, that's a call to `setup_git_directory_gently()`, and obviously we already know a couple of scenarios where the `GIT_DIR` environment variable is _not_ set in this function.

Unfortunately, this function is a bit long and calls other functions, too: https://github.com/git/git/blob/v2.33.1/setup.c#L1206-L1339

I actually believe that the `GIT_DIR` is set (_when_ it is set) in `set_git_dir_1()`: https://github.com/git/git/blob/v2.33.1/environment.c#L332. This function is called, unconditionally, in `set_git_dir()`, so my best bet is that the `set_git_dir()` function calls in `setup_git_directory_gently()` are the reason why `GIT_DIR` is set sometimes, but not always.

And it is further my suspicion that calls to `set_git_dir()` are used to potentially turn a relative path into an absolute one, by passing a non-zero value for `make_realpath`. And this might be the reason for the calls in the first place, not the `GIT_DIR` variable.

So the first step would probably be to write a test case (see the scripts in t/) that creates a secondary worktree, then calls an alias that verifies that `GIT_DIR` is not set when run in that worktree. This test case would be marked with `test_expect_failure`.

Then, you need to debug that test case (e.g. by using the `debug` function to run a given Git command through `gdb` and then setting a breakpoint on `setenv()`). Once you have the call path of the offending `setenv()`, you might find an elegant way to avoid setting the environment variable.

On the other hand, you could also simply unset `GIT_DIR` and friends explicitly, by adding something like this after https://github.com/git/git/blob/v2.33.1/git.c#L364:

	strvec_push(&child.env, "GIT_DIR");

But then, you might actually break things. The `GIT_PREFIX` variable is required to let aliases know in which subdirectory (if any) they were started. For example, if you run this command in Git's `Documentation/` directory, it will actually print the path of the top-level directory:

	git -c alias.pwd='!pwd' pwd

This is long-established behavior, and the only way to go back to the directory from where the alias was started is to call `cd "$GIT_PREFIX"`. That's behavior, therefore, that you cannot change.

And if `GIT_PREFIX` needs to be set, maybe there are scenarios where `GIT_DIR` actually _does_ need to be set?

Hopefully these explanations make some sense to you.

Ciao, Johannes

Previous: Federico Kircheis
Message 5 of 5 in “git aliases and GIT_PREFIX”
  1. Federico KircheisOct 28, 2021
  2. Ævar Arnfjörð BjarmasonOct 29, 2021
  3. Johannes SchindelinNov 2, 2021
  4. Federico KircheisNov 2, 2021
  5. Johannes SchindelinNov 4, 2021

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.