threads / discuss / 9995

behaviour of git diff, GIT_DIR & checked out tree

Subject: behaviour of git diff, GIT_DIR & checked out tree

## tl;dr

6 messages between Sep 24, 2007 and Sep 24, 2007.

replies: 5people: 3as markdown or json

David Tweed· Sep 24, 2007, 12:45 UTC · lore

I'm doing something "sensible people don't do" -- I know this -- but I'm getting results I don't understand, so I'd appreciate any insight.

In a git tracked tree rooted at $HOME/V with git-dir of $HOME/V/.git, if I'm in $HOME/V then

git diff master@{midnight}

tells me the difference between the current modified files in the tree being tracked in V and the specified commit. In a different directory, OUTSIDE of $HOME/V, I tried

env GIT_DIR=$HOME/V/.git git diff master@{midnight}

to get the same effect but, whilst I do get a diff output, it looks like a diff of the commit against an empty tree. (Using

env GIT_DIR=$HOME/V/.git git diff HEAD master@{midnight}
works ok.) I suppose I could alias it to
cd $HOME/V && command && cd -

but that seems a bit clunky; is there another way to explicitly say "working tree for repo with this GIT_DIR" to git diff?

[Why I'm doing this: I actually work on files in the $HOME/V via various other directories containing symlinks to the basic files (with tracked files being pointed to by multiple symlinks). So I'm almost never actually "in" the tracked tree. This usage makes more sense for my tasks than being within the work tree.]

-- 
cheers, dave tweed__________________________
david.tweed@gmail.com
Rm 124, School of Systems Engineering, University of Reading.
"we had no idea that when we added templates we were adding a Turing-
complete compile-time language." -- C++ standardisation committee
Johannes Schindelin· Sep 24, 2007, 13:03 UTC · re: David Tweed · lore

Re: behaviour of git diff, GIT_DIR & checked out tree

Hi,
On Mon, 24 Sep 2007, David Tweed wrote:
Show 13 quoted lines
> In a git tracked tree rooted at $HOME/V with
> git-dir of $HOME/V/.git, if I'm in $HOME/V then
> 
> git diff master@{midnight}
> 
> tells me the difference between the current modified files
> in the tree being tracked in V and the specified commit. In
> a different directory, OUTSIDE of $HOME/V, I tried
> 
> env GIT_DIR=$HOME/V/.git git diff master@{midnight}
> 
> to get the same effect but, whilst I do get a diff output, it
> looks like a diff of the commit against an empty tree.
Yes, this is fully expected.

The @{time} notation accesses the _reflogs_, which are purely local beasts. They are not transmitted when cloning.

The rationale: in a distributed environment, you cannot trust others' timestamps. Therefore we don't.

We can only (to a certain extent, at least) trust our _own_ timestamp. That is why we have timestamp access to the reflogs (which are purely local, as I mentioned above), but we have no way to reference commits by timestamp otherwise.

Hth, Dscho

David Tweed· Sep 24, 2007, 13:16 UTC · re: Johannes Schindelin · lore

Re: behaviour of git diff, GIT_DIR & checked out tree

On 9/24/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Yes, this is fully expected.
>
> The @{time} notation accesses the _reflogs_, which are purely local
> beasts.  They are not transmitted when cloning.

Thanks of your reply; however I suspect this isn't the problem here since I just tried with just master and I get the same thing. To be clear, I'm doing this on the same machine with the same user account as the git directory, just from a directory outside the git tree, eg, the git tracked tree is in $HOME/V and I'm in $HOME/A running

env GIT_DIR=$HOME/V/.git git diff master

As a guess without looking at the code, what I imagine is happening is that git diff limits showing changes to the directory tree below $PWD, and when $PWD isn't actually within the git dir that ends up somehow as an empty tree.

-- 
cheers, dave tweed__________________________
david.tweed@gmail.com
Rm 124, School of Systems Engineering, University of Reading.
"we had no idea that when we added templates we were adding a Turing-
complete compile-time language." -- C++ standardisation committee
Junio C Hamano· Sep 24, 2007, 16:47 UTC · re: Johannes Schindelin · lore

Re: behaviour of git diff, GIT_DIR & checked out tree

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 14 quoted lines
> On Mon, 24 Sep 2007, David Tweed wrote:
>
>> ... In
>> a different directory, OUTSIDE of $HOME/V, I tried
>> 
>> env GIT_DIR=$HOME/V/.git git diff master@{midnight}
>> 
>> to get the same effect but, whilst I do get a diff output, it
>> looks like a diff of the commit against an empty tree.
>
> Yes, this is fully expected.
>
> The @{time} notation accesses the _reflogs_, which are purely local 
> beasts.  They are not transmitted when cloning.

Yeah, but my reading of the problem description suggests the two cases refer to the same repository (hence the same reflogs).

The issue is that the second case runs "git diff <one-tree>" in a random directory. This form is about comparing the part of work tree you are in with a given tree, and does not make _any_ sense when outside the work tree. Usually without GIT_DIR environment, the command would give you an error message.

With $GIT_DIR, but without $GIT_WORK_TREE, the user is telling the command that it is being run at the top level of the work tree and the repository metadata is not in the usual ".git" subdirectory of the top level of the work tree (in this case, by definition that is "$PWD/.git") but elsewhere where $GIT_DIR specifies. Because it is very likely that the files under the random location does not share much resemblance to what are in $HOME/V, it is not surprising that the output consisted of many deletions.

It would be illustrative if David did the following.
	$ cd $HOME
        $ cp -a V W
        $ rm -fr W/.git
        $ cd W
        $ GIT_DIR=$HOME/V/.git git diff @{midnight}

Now we are in a random place outside of the work tree (i.e. "W"), and we drive "git diff" with GIT_DIR specified, telling it to pretend that we are at the top level of the work tree. So ~/W/frotz is compared with "frotz" at the top level of the commit (which usually is compared with ~/V/frotz), etc. But the directory we happen to be in very much resembles the work tree, so it would give identical results to

	$ cd $HOME/V
        $ git diff @{midnight}
David Tweed· Sep 24, 2007, 17:09 UTC · re: Junio C Hamano · lore

Re: behaviour of git diff, GIT_DIR & checked out tree

On 9/24/07, Junio C Hamano <gitster@pobox.com> wrote:
Show 18 quoted lines
> It would be illustrative if David did the following.
>
>         $ cd $HOME
>         $ cp -a V W
>         $ rm -fr W/.git
>         $ cd W
>         $ GIT_DIR=$HOME/V/.git git diff @{midnight}
>
> Now we are in a random place outside of the work tree
> (i.e. "W"), and we drive "git diff" with GIT_DIR specified,
> telling it to pretend that we are at the top level of the work
> tree.  So ~/W/frotz is compared with "frotz" at the top level of
> the commit (which usually is compared with ~/V/frotz), etc.  But
> the directory we happen to be in very much resembles the work
> tree, so it would give identical results to
>
>         $ cd $HOME/V
>         $ git diff @{midnight}

To separate the two issues, I did all the commands to the diff above and then removed one directory from the tree in W.

GIT_DIR=$HOME/V/.git git diff master~1 (which ought not need reflogs, right) and it gave a diff between the contents of W and master~1. I also tried with commit master@{midnight} and that also gave the difference between W and the last commit yesterday. So Junio's explanation of what's going on is right. I'm just asking if there's a way to say "the `working dir' associated with this git dir" explicitly (in the same way I can use `HEAD' to refer to the topmost commit on the current branch) when you're not somewhere within the 'working dir'. If there's not I can alias around it with "cd $HOME/V && command && cd -". (As I say, for reasons unrelated to git usage I don't actually "do work" within the tracked tree.)

Many thanks,
-- 
cheers, dave tweed__________________________
david.tweed@gmail.com
Rm 124, School of Systems Engineering, University of Reading.
"we had no idea that when we added templates we were adding a Turing-
complete compile-time language." -- C++ standardisation committee
Junio C Hamano· Sep 24, 2007, 18:31 UTC · re: David Tweed · lore

Re: behaviour of git diff, GIT_DIR & checked out tree

"David Tweed" <david.tweed@gmail.com> writes:
> ... I'm just asking if there's a way to say
> "the `working dir' associated with this git dir" explicitly (in the same
> way I can use `HEAD' to refer to the topmost commit on the
> current branch) when you're not somewhere within the 'working dir'.

Not for "git diff <one-tree>" which is a way to diff the _part_ of work tree you are _currently in_ with the given tree, nor for "git diff" which is to do the same with the index. With these commands (and others that error out when you run without GIT_DIR outside the work tree), you are really expected to be _in_ the subdirectory you are interested in.

GIT_WORK_TREE is somewhat related but is a different issue, by the way. It is to let you say where the top level of the work tree is. It does not change the fact that the way for you to express which subdirectory in the work tree you are interested in to work tree commands is by your $PWD relative to the top of the work tree.

← back to recent threads