git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Weird output of git status in pre-commit hook when providing a pathspec on commit
@ 2015-02-03 13:14 Michaël Fortin
  2015-02-03 16:32 ` Jeff King
  0 siblings, 1 reply; 3+ messages in thread
From: Michaël Fortin @ 2015-02-03 13:14 UTC (permalink / raw)
  To: git

Hi all,

I'm seeing behavior that I *think* might be a bug in git (I'm running 2.2.2). At least I couldn't find anything about this anywhere, so here goes:

I'm trying to run git commands outside of the current working copy (e.g. inside another repo) from a pre-commit hook. However I'm encountering a very weird issue that occurs when a pathspec is provided when performing a commit.

More precisely, what I'm trying to do is check whether a repository beside the current repository is clean (no uncommitted changes) or not, from a pre-commit hook.

My repositories look like this on disk:

ContainerDirectory
|-- Repo1 (contains one untracked file)
|-- Repo2 (no uncommitted changes)

Repo1 has the following pre-commit hook:

#!/bin/bash
git -C "../Repo2" status --porcelain

I then commit in Repo1 using the following (this is actually ran by a GUI, I have no control over the commands themselves):

git add --force -- MyNewFile
git commit -m "My message" -o -- MyNewFile

This results in some very puzzling output. I would expect the hook to output nothing because Repo2 contains no changes. However, it returns the following:

D  Repo2-File1.txt
D  Repo2-File2.txt
D  Repo2-File3.txt
?? Repo2-File1.txt
?? Repo2-File2.txt
?? Repo2-File3.txt

As you can see, the files are listed as both deleted and untracked, which makes no sense to me because there are in fact no uncommitted changes in that repo. There are only these three files in the repo. Removing the pathspec ("-- MyNewFile") from the commit command shows the expected output (nothing, because there are no changes in Repo2).

I have reproduced this behavior on OS X and Windows (with the latest git for Windows).

Can you explain what's going on?

Thanks in advance for any info!

Michaël Fortin
www.irradiated.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Weird output of git status in pre-commit hook when providing a pathspec on commit
  2015-02-03 13:14 Weird output of git status in pre-commit hook when providing a pathspec on commit Michaël Fortin
@ 2015-02-03 16:32 ` Jeff King
  2015-02-04 22:45   ` Michaël Fortin
  0 siblings, 1 reply; 3+ messages in thread
From: Jeff King @ 2015-02-03 16:32 UTC (permalink / raw)
  To: Michaël Fortin; +Cc: git

On Tue, Feb 03, 2015 at 08:14:06AM -0500, Michaël Fortin wrote:

> Repo1 has the following pre-commit hook:
> 
> #!/bin/bash
> git -C "../Repo2" status --porcelain
> 
> I then commit in Repo1 using the following (this is actually ran by a
> GUI, I have no control over the commands themselves):
> 
> git add --force -- MyNewFile
> git commit -m "My message" -o -- MyNewFile

Because the commit command uses "-o", git must use a temporary index
file to stage the commit. It sets GIT_INDEX_FILE in the environment, and
then runs your hook.

When the hook runs "git -C" it moves into another repository, but the
GIT_INDEX_FILE in the environment takes precedence over the local index
found in that repository. So you see a HEAD and working tree from Repo2,
but the index from Repo1.

This is a specific case of a more general problem. If you were to run
git like:

  git --git-dir=/path/to/.git commit ...

you would have similar problems. You would have $GIT_DIR set in the
environment, and would see the HEAD from Repo1, but the working tree
from Repo2.

In other words, moving into another git directory from inside a hook is
not as easy as just going there. You also need to clear any state from
the environment. E.g., by adding this to the top of your hook:

  unset $(git rev-parse --local-env-vars)

Should "-C" (or "--git-dir") make this easier by doing it for you? I'm
not sure it is a good idea. It is right now valid to do:

  GIT_INDEX_FILE=/path/to/index.tmp git -C /path/to/repo ...

which would break if we cleared git variables. OTOH, maybe using "-C"
(instead of chdir-ing yourself) is a good indication that you want that
cleared. I dunno. It is probably too late at this point, as we would be
subtly breaking backwards compatibility. Perhaps it would make more
sense to add a new option, so you could do:

  git --reset-git-vars -C ../Repo2 status --porcelain

But this is a fairly obscure use case, and the rev-parse invocation
above is not so bad. I think it is more about knowing that you need to
use it, rather than the pain of typing it. And I am not sure how to make
that more clear. Is there a specific place in the documentation you
looked and might have been warned? Maybe the description for "-C" should
cover this.

-Peff

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Weird output of git status in pre-commit hook when providing a pathspec on commit
  2015-02-03 16:32 ` Jeff King
@ 2015-02-04 22:45   ` Michaël Fortin
  0 siblings, 0 replies; 3+ messages in thread
From: Michaël Fortin @ 2015-02-04 22:45 UTC (permalink / raw)
  To: Jeff King; +Cc: git

Interesting!

Thanks for the info; unsetting git environment variables as you suggested fixes my issue on OS X (and Linux I suppose). I’m going to try this on Windows soon. Would that work as-is on Windows, or would I need to unset the vars using some other Windows-specific syntax?

Yes, I looked at the documentation for “-C", and “-o". Because this issue is triggered by the use of “-o”, maybe the appropriate place to mention this behaviour would be in the documentation for “-o”? I don’t know.

Thanks again,

Michaël Fortin
www.irradiated.net

> On Feb 3, 2015, at 11:32 AM, Jeff King <peff@peff.net> wrote:
> 
> On Tue, Feb 03, 2015 at 08:14:06AM -0500, Michaël Fortin wrote:
> 
>> Repo1 has the following pre-commit hook:
>> 
>> #!/bin/bash
>> git -C "../Repo2" status --porcelain
>> 
>> I then commit in Repo1 using the following (this is actually ran by a
>> GUI, I have no control over the commands themselves):
>> 
>> git add --force -- MyNewFile
>> git commit -m "My message" -o -- MyNewFile
> 
> Because the commit command uses "-o", git must use a temporary index
> file to stage the commit. It sets GIT_INDEX_FILE in the environment, and
> then runs your hook.
> 
> When the hook runs "git -C" it moves into another repository, but the
> GIT_INDEX_FILE in the environment takes precedence over the local index
> found in that repository. So you see a HEAD and working tree from Repo2,
> but the index from Repo1.
> 
> This is a specific case of a more general problem. If you were to run
> git like:
> 
>  git --git-dir=/path/to/.git commit ...
> 
> you would have similar problems. You would have $GIT_DIR set in the
> environment, and would see the HEAD from Repo1, but the working tree
> from Repo2.
> 
> In other words, moving into another git directory from inside a hook is
> not as easy as just going there. You also need to clear any state from
> the environment. E.g., by adding this to the top of your hook:
> 
>  unset $(git rev-parse --local-env-vars)
> 
> Should "-C" (or "--git-dir") make this easier by doing it for you? I'm
> not sure it is a good idea. It is right now valid to do:
> 
>  GIT_INDEX_FILE=/path/to/index.tmp git -C /path/to/repo ...
> 
> which would break if we cleared git variables. OTOH, maybe using "-C"
> (instead of chdir-ing yourself) is a good indication that you want that
> cleared. I dunno. It is probably too late at this point, as we would be
> subtly breaking backwards compatibility. Perhaps it would make more
> sense to add a new option, so you could do:
> 
>  git --reset-git-vars -C ../Repo2 status --porcelain
> 
> But this is a fairly obscure use case, and the rev-parse invocation
> above is not so bad. I think it is more about knowing that you need to
> use it, rather than the pain of typing it. And I am not sure how to make
> that more clear. Is there a specific place in the documentation you
> looked and might have been warned? Maybe the description for "-C" should
> cover this.
> 
> -Peff

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-02-04 22:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-03 13:14 Weird output of git status in pre-commit hook when providing a pathspec on commit Michaël Fortin
2015-02-03 16:32 ` Jeff King
2015-02-04 22:45   ` Michaël Fortin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).