threads / bug / 20166

bug with .git file and aliases

Subject: bug with .git file and aliases

## tl;dr

13 messages between Jul 20, 2009 and Aug 11, 2009.

replies: 12people: 6as markdown or json

Geoffrey Irving· Jul 20, 2009, 13:54 UTC · lore
git 1.6.3.3 has a bug related to .git file support and aliases.
Specifically, if you make an alias for status and call it from a
subdirectory, git status chdirs into the true .git dir but then
chdir's back to the wrong place in order to run the lstats for status.
 The result is that git status thinks all files have disappeared.
Here's a self-contained test script:
    #!/bin/bash
    set -x
    # make a simple repository
    mkdir repo
    cd repo
    git init
    mkdir a
    echo content > a/b
    git add a/b
    git commit -m "a commit"
    # replace the gitdir with a gitfile
    mv .git ../repo.git
    echo gitdir: `pwd`.git > .git
    # normal git status works
    cd a
    git status
    # an alias for git status fails
    git config alias.st status
    git st
which produces output
top:tmp% ./bug
++ mkdir repo
++ cd repo
++ git init
Initialized empty Git repository in /Users/irving/tmp/tmp/repo/.git/
++ mkdir a
++ echo content
++ git add a/b
++ git commit -m 'a commit'
[master (root-commit) 6b07ec4] a commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 a/b
++ mv .git ../repo.git
+++ pwd
++ echo gitdir: /Users/irving/tmp/tmp/repo.git
++ cd a
++ git status
# On branch master
nothing to commit (working directory clean)
++ git config alias.st status
++ git st
# On branch master
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	deleted:    a/b
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	b
no changes added to commit (use "git add" and/or "git commit -a")

.git file support also doesn't work on a repository with no commits (which is why the test script makes a commit normally before switching to a gitfile). However, I care about this second problem much less, and didn't notice it until I made the test script.

Finally, huge thanks to Lars for implementing this. I'm storing git working directories inside vesta, and symlink support is currently disabled. It's very pleasant to grep through the source and find that someone already fixed exactly my problem. :)

Geoffrey
Santi Béjar· Jul 20, 2009, 14:04 UTC · re: Geoffrey Irving · lore

Re: bug with .git file and aliases

2009/7/20 Geoffrey Irving <irving@naml.us>:
Show 31 quoted lines
> git 1.6.3.3 has a bug related to .git file support and aliases.
> Specifically, if you make an alias for status and call it from a
> subdirectory, git status chdirs into the true .git dir but then
> chdir's back to the wrong place in order to run the lstats for status.
>  The result is that git status thinks all files have disappeared.
>
> Here's a self-contained test script:
>
>    #!/bin/bash
>    set -x
>
>    # make a simple repository
>    mkdir repo
>    cd repo
>    git init
>    mkdir a
>    echo content > a/b
>    git add a/b
>    git commit -m "a commit"
>
>    # replace the gitdir with a gitfile
>    mv .git ../repo.git
>    echo gitdir: `pwd`.git > .git
>
>    # normal git status works
>    cd a
>    git status
>
>    # an alias for git status fails
>    git config alias.st status
>    git st

I suspect that the $GIR_DIR and .git file works equally in this aspect, so you should specify where is the workdir in .git/config with respect the repository:

git config core.workdir `pwd`

HTH, Santi

Geoffrey Irving· Jul 20, 2009, 14:27 UTC · re: Santi Béjar · lore

Re: bug with .git file and aliases

On Mon, Jul 20, 2009 at 10:04 AM, Santi Béjar<santi@agolina.net> wrote:
Show 5 quoted lines
> I suspect that the $GIR_DIR and .git file works equally in this
> aspect, so you should specify where is the workdir in .git/config with
> respect the repository:
>
> git config core.workdir `pwd`
Nope, that has no effect.
By the way, I can work around this problem by using
    git config alias.st "!git status"
but unfortunately that has slightly different behavior (it ignores pwd).
Geoffrey
Santi Béjar· Jul 20, 2009, 15:18 UTC · re: Geoffrey Irving · lore

Re: bug with .git file and aliases

2009/7/20 Geoffrey Irving <irving@naml.us>:
Show 8 quoted lines
> On Mon, Jul 20, 2009 at 10:04 AM, Santi Béjar<santi@agolina.net> wrote:
>> I suspect that the $GIR_DIR and .git file works equally in this
>> aspect, so you should specify where is the workdir in .git/config with
>> respect the repository:
>>
>> git config core.workdir `pwd`
>
> Nope, that has no effect.

Here it has the desired effect. From where did you run the above command? What is the output of:

git config core.workdir
?
It should output the path of the repo, not of the "a" subdirectory.

HTH, Santi

Geoffrey Irving· Jul 20, 2009, 15:25 UTC · re: Santi Béjar · lore

Re: bug with .git file and aliases

On Mon, Jul 20, 2009 at 11:18 AM, Santi Béjar<santi@agolina.net> wrote:
Show 14 quoted lines
> 2009/7/20 Geoffrey Irving <irving@naml.us>:
>> On Mon, Jul 20, 2009 at 10:04 AM, Santi Béjar<santi@agolina.net> wrote:
>>> I suspect that the $GIR_DIR and .git file works equally in this
>>> aspect, so you should specify where is the workdir in .git/config with
>>> respect the repository:
>>>
>>> git config core.workdir `pwd`
>>
>> Nope, that has no effect.
>
> Here it has the desired effect. From where did you run the above
> command? What is the output of:
>
> git config core.workdir

top:a% git config core.workdir /Users/irving/tmp/tmp/repo top:a% git st # On branch master # Changed but not updated: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: a/b # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # b

It doesn't matter, though, since setting workdir should not be necessary.
Geoffrey
Jeff King· Jul 20, 2009, 15:21 UTC · re: Geoffrey Irving · lore

Re: bug with .git file and aliases

On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
Show 5 quoted lines
> git 1.6.3.3 has a bug related to .git file support and aliases.
> Specifically, if you make an alias for status and call it from a
> subdirectory, git status chdirs into the true .git dir but then
> chdir's back to the wrong place in order to run the lstats for status.
>  The result is that git status thinks all files have disappeared.

Yeah, this is a known problem. The problem is that the 'git' wrapper sets up the environment only partially when running aliases, and then the resulting command ends up confused about where the worktree is. I really don't remember the specifics, but you can probably find some discussion in the list archives. Fixing it, IIRC, required some refactoring of the setup code (which I had hoped to get to at some point, but I am way behind on my git todo list).

Hmm. Poking around a bit, this seems related, but I don't know why I never followed up:

  http://article.gmane.org/gmane.comp.version-control.git/72792
-Peff
Geoffrey Irving· Aug 10, 2009, 20:22 UTC · re: Jeff King · lore

Re: bug with .git file and aliases

On Mon, Jul 20, 2009 at 11:21 AM, Jeff King<peff@peff.net> wrote:
Show 15 quoted lines
> On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
>
>> git 1.6.3.3 has a bug related to .git file support and aliases.
>> Specifically, if you make an alias for status and call it from a
>> subdirectory, git status chdirs into the true .git dir but then
>> chdir's back to the wrong place in order to run the lstats for status.
>>  The result is that git status thinks all files have disappeared.
>
> Yeah, this is a known problem. The problem is that the 'git' wrapper
> sets up the environment only partially when running aliases, and then
> the resulting command ends up confused about where the worktree is. I
> really don't remember the specifics, but you can probably find some
> discussion in the list archives.  Fixing it, IIRC, required some
> refactoring of the setup code (which I had hoped to get to at some
> point, but I am way behind on my git todo list).

The attached patch fixes the bug for me. I'll leave it to others to determine whether this is a good way to fix the problem.

Thanks, Geoffrey

From ec47aa09e5bc8d9a8c07cca9f8ef17a9898819c1 Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <irving@naml.us>
Date: Mon, 10 Aug 2009 15:59:21 -0400
Subject: [PATCH] setup.c: fix work tree setup for .git-files and aliases

When .git-files and aliases are used together, the setup machinery gets confused and ends up with the wrong work_tree. Specifically, git_work_tree_cfg is set to the correct value first, but set_work_tree resets git_work_tree_cfg to the current directory, which (at least in this case) is incorrect.

set_work_tree now detects this case by checking to see if git_work_tree_cfg is already set. If so, it leaves git_work_tree_cfg unchanged and instead uses the current directory to compute and return the correct prefix (where we are relative to the work tree).

Signed-off-by: Geoffrey Irving <irving@naml.us>
---
 setup.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/setup.c b/setup.c
index e3781b6..97f7eb1 100644
--- a/setup.c
+++ b/setup.c
@@ -198,13 +198,24 @@ int is_inside_work_tree(void)
 static const char *set_work_tree(const char *dir)
 {
 	char buffer[PATH_MAX + 1];
+	size_t offset;
 
 	if (!getcwd(buffer, sizeof(buffer)))
 		die ("Could not get the current working directory");
-	git_work_tree_cfg = xstrdup(buffer);
 	inside_work_tree = 1;
 
-	return NULL;
+	if (!git_work_tree_cfg) {
+		git_work_tree_cfg = xstrdup(buffer);
+		return NULL;
+	} else {
+		offset = strlen(git_work_tree_cfg);
+		if (memcmp(git_work_tree_cfg, buffer, offset)
+			|| (buffer[offset] && buffer[offset] != '/'))
+			die ("fatal: not inside work tree (should not happen)");
+		if (!buffer[offset] || !buffer[offset+1])
+			return NULL;
+		return xstrdup(strcat(buffer + offset + 1, "/"));
+	}
 }
 
 void setup_work_tree(void)
-- 
1.6.3.3
Johannes Schindelin· Aug 10, 2009, 23:05 UTC · re: Geoffrey Irving · lore

Re: bug with .git file and aliases

Hi,
On Mon, 10 Aug 2009, Geoffrey Irving wrote:
Show 19 quoted lines
> On Mon, Jul 20, 2009 at 11:21 AM, Jeff King<peff@peff.net> wrote:
> > On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
> >
> >> git 1.6.3.3 has a bug related to .git file support and aliases.
> >> Specifically, if you make an alias for status and call it from a
> >> subdirectory, git status chdirs into the true .git dir but then
> >> chdir's back to the wrong place in order to run the lstats for status.
> >>  The result is that git status thinks all files have disappeared.
> >
> > Yeah, this is a known problem. The problem is that the 'git' wrapper
> > sets up the environment only partially when running aliases, and then
> > the resulting command ends up confused about where the worktree is. I
> > really don't remember the specifics, but you can probably find some
> > discussion in the list archives.  Fixing it, IIRC, required some
> > refactoring of the setup code (which I had hoped to get to at some
> > point, but I am way behind on my git todo list).
> 
> The attached patch fixes the bug for me.  I'll leave it to others to
> determine whether this is a good way to fix the problem.

Note that you made it particularly hard to comment on your patch by not granting us the wish stated in Documentation/SubmittingPatches, namely to inline your patch.

I'll just forego inlining it myself, as I am way past my bed-time and cannot be bothered.

However, I think that it is necessary to comment on your patch.

There is a few style issues, such as declaring offset outside of the block that is the only user, and there is the issue that you go out of your way to append a slash if you're resetting the work tree, but not when not resetting it.

But the bigger issue is that you now broke overriding the work tree via the command line.

The proper fix, of course, is to avoid calling the function with the wrong path to begin with.

Ciao, Dscho

Geoffrey Irving· Aug 11, 2009, 03:37 UTC · re: Johannes Schindelin · lore

Re: bug with .git file and aliases

On Mon, Aug 10, 2009 at 7:05 PM, Johannes Schindelin<Johannes.Schindelin@gmx.de> wrote:

Show 30 quoted lines
> Hi,
>
> On Mon, 10 Aug 2009, Geoffrey Irving wrote:
>
>> On Mon, Jul 20, 2009 at 11:21 AM, Jeff King<peff@peff.net> wrote:
>> > On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
>> >
>> >> git 1.6.3.3 has a bug related to .git file support and aliases.
>> >> Specifically, if you make an alias for status and call it from a
>> >> subdirectory, git status chdirs into the true .git dir but then
>> >> chdir's back to the wrong place in order to run the lstats for status.
>> >>  The result is that git status thinks all files have disappeared.
>> >
>> > Yeah, this is a known problem. The problem is that the 'git' wrapper
>> > sets up the environment only partially when running aliases, and then
>> > the resulting command ends up confused about where the worktree is. I
>> > really don't remember the specifics, but you can probably find some
>> > discussion in the list archives.  Fixing it, IIRC, required some
>> > refactoring of the setup code (which I had hoped to get to at some
>> > point, but I am way behind on my git todo list).
>>
>> The attached patch fixes the bug for me.  I'll leave it to others to
>> determine whether this is a good way to fix the problem.
>
> Note that you made it particularly hard to comment on your patch by not
> granting us the wish stated in Documentation/SubmittingPatches, namely to
> inline your patch.
>
> I'll just forego inlining it myself, as I am way past my bed-time and
> cannot be bothered.
Oops.  Here's the inlined patch with offset fixed, for others:
From ec47aa09e5bc8d9a8c07cca9f8ef17a9898819c1 Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <irving@naml.us>
Date: Mon, 10 Aug 2009 15:59:21 -0400
Subject: [PATCH] setup.c: fix work tree setup for .git-files and aliases

When .git-files and aliases are used together, the setup machinery gets confused and ends up with the wrong work_tree. Specifically, git_work_tree_cfg is set to the correct value first, but set_work_tree resets git_work_tree_cfg to the current directory, which (at least in this case) is incorrect.

set_work_tree now detects this case by checking to see if git_work_tree_cfg is already set. If so, it leaves git_work_tree_cfg unchanged and instead uses the current directory to compute and return the correct prefix (where we are relative to the work tree).

Signed-off-by: Geoffrey Irving <irving@naml.us>
---
 setup.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/setup.c b/setup.c
index e3781b6..97f7eb1 100644
--- a/setup.c
+++ b/setup.c
@@ -198,13 +198,24 @@ int is_inside_work_tree(void)
 static const char *set_work_tree(const char *dir)
 {
 	char buffer[PATH_MAX + 1];

 	if (!getcwd(buffer, sizeof(buffer)))
 		die ("Could not get the current working directory");
-	git_work_tree_cfg = xstrdup(buffer);
 	inside_work_tree = 1;

-	return NULL;
+	if (!git_work_tree_cfg) {
+		git_work_tree_cfg = xstrdup(buffer);
+		return NULL;
+	} else {
+		size_t offset = strlen(git_work_tree_cfg);
+		if (memcmp(git_work_tree_cfg, buffer, offset)
+			|| (buffer[offset] && buffer[offset] != '/'))
+			die ("fatal: not inside work tree (should not happen)");
+		if (!buffer[offset] || !buffer[offset+1])
+			return NULL;
+		return xstrdup(strcat(buffer + offset + 1, "/"));
+	}
 }

 void setup_work_tree(void)
-- 
1.6.3.3

> However, I think that it is necessary to comment on your patch.
>
> There is a few style issues, such as declaring offset outside of the
> block that is the only user, and there is the issue that you go out of
> your way to append a slash if you're resetting the work tree, but not when
> not resetting it.
>
> But the bigger issue is that you now broke overriding the work tree via
> the command line.
>
> The proper fix, of course, is to avoid calling the function with the wrong
> path to begin with.

I'm happy that the correct fix is obvious, and apologize for missing it.

Geoffrey
Johannes Schindelin· Aug 11, 2009, 08:33 UTC · re: Geoffrey Irving · lore

Re: bug with .git file and aliases

Hi,
On Mon, 10 Aug 2009, Geoffrey Irving wrote:
Show 7 quoted lines
> On Mon, Aug 10, 2009 at 7:05 PM, Johannes
> Schindelin<Johannes.Schindelin@gmx.de> wrote:
>
> > The proper fix, of course, is to avoid calling the function with the 
> > wrong path to begin with.
> 
> I'm happy that the correct fix is obvious, and apologize for missing it.

No, no, I said that it is obvious what should be fixed (you do not want to break perfectly valid workflows such as having a worktree set in the config, but overriding it via git's --work-tree option). The fix is not obvious, unfortunately.

See also http://thread.gmane.org/gmane.comp.version-control.git/102269 for some discussion on the same topic.

Ciao, Dscho

Michael J Gruber· Aug 11, 2009, 10:04 UTC · re: Jeff King · lore

Re: bug with .git file and aliases

Jeff King venit, vidit, dixit 20.07.2009 17:21:
Show 22 quoted lines
> On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
> 
>> git 1.6.3.3 has a bug related to .git file support and aliases.
>> Specifically, if you make an alias for status and call it from a
>> subdirectory, git status chdirs into the true .git dir but then
>> chdir's back to the wrong place in order to run the lstats for status.
>>  The result is that git status thinks all files have disappeared.
> 
> Yeah, this is a known problem. The problem is that the 'git' wrapper
> sets up the environment only partially when running aliases, and then
> the resulting command ends up confused about where the worktree is. I
> really don't remember the specifics, but you can probably find some
> discussion in the list archives.  Fixing it, IIRC, required some
> refactoring of the setup code (which I had hoped to get to at some
> point, but I am way behind on my git todo list).
> 
> Hmm. Poking around a bit, this seems related, but I don't know why I
> never followed up:
> 
>   http://article.gmane.org/gmane.comp.version-control.git/72792
> 
> -Peff

...because it was up to the brave git-on-win folks to decide whether setenv() on win would be rewritten to not use putenv() when the value is "". J&J, has anything happened on the front or is it likely to? (I'm sorry I can't offer help, only moral support...)

Jeff's patch from Feb. 08 still applies more or less cleanly (with obvious adjustments) and makes the relevant tests pass (on Linux).

Michael
Johannes Sixt· Aug 11, 2009, 10:26 UTC · re: Michael J Gruber · lore

Re: bug with .git file and aliases

Michael J Gruber schrieb:
> ...because it was up to the brave git-on-win folks to decide whether
> setenv() on win would be rewritten to not use putenv() when the value is
> "". J&J, has anything happened on the front or is it likely to? (I'm
> sorry I can't offer help, only moral support...)

Nothing has changed since. Nothing is likely to happen until there is a need to touch compat/setenv.c, like, for example, a test in the test suite that fails only on Windows...

-- Hannes
Michael J Gruber· Aug 11, 2009, 10:37 UTC · re: Johannes Sixt · lore

Re: bug with .git file and aliases

Johannes Sixt venit, vidit, dixit 11.08.2009 12:26:
Show 9 quoted lines
> Michael J Gruber schrieb:
>> ...because it was up to the brave git-on-win folks to decide whether
>> setenv() on win would be rewritten to not use putenv() when the value is
>> "". J&J, has anything happened on the front or is it likely to? (I'm
>> sorry I can't offer help, only moral support...)
> 
> Nothing has changed since. Nothing is likely to happen until there is a
> need to touch compat/setenv.c, like, for example, a test in the test suite
> that fails only on Windows...
...well, that can be taken care of quickly. Go, Jeff, go :)
Michael

← back to recent threads