Subject: Re: weird behaviour in git

From: Michael J Gruber <[email-masked]>
Date: Thu, 26 Feb 2015 16:22:32 +0100

Thomas Klausner venit, vidit, dixit 26.02.2015 15:58:
> On Thu, Feb 26, 2015 at 03:45:13PM +0100, Michael J Gruber wrote:
>> Thomas Klausner venit, vidit, dixit 26.02.2015 15:12:
>>> Hi!
>>>
>>> I've played around with git and found that 'git mv' does not honor
>>> what I tell it to do:
>>>
>>> wiz@yt:~> mkdir a
>>> wiz@yt:~> cd a
>>> wiz@yt:~/a> git init .
>>> Initialized empty Git repository in /home/wiz/a/.git/
>>> wiz@yt:~/a> touch a
>>> wiz@yt:~/a> git add a
>>> wiz@yt:~/a> git commit -m 'add a'
>>> [master (root-commit) 99d0ee7] add a
>>>  1 file changed, 0 insertions(+), 0 deletions(-)
>>>  create mode 100644 a
>>> wiz@yt:~/a> git mv a b
>>> wiz@yt:~/a> touch Makefile
>>> wiz@yt:~/a> git add Makefile
>>> wiz@yt:~/a> git commit
>>>
>>>
>>> # Please enter the commit message for your changes. Lines starting
>>> # with '#' will be ignored, and an empty message aborts the commit.
>>> # On branch master
>>> # Changes to be committed:
>>> #       renamed:    a -> Makefile
>>> #       new file:   b
>>> #
>>>
>>> This is reproducible for me with "git version 2.3.0" on
>>> NetBSD-7.99.5/amd64.
>>>
>>> I guess this happens because the checksums of the files are the same
>>> and 'Makefile' is earlier when sorting, but since I explicitly told
>>> "git mv" old and new name, I think that's a bug nevertheless.
>>>  Thomas
>>>
>>
>> git tracks content, not paths.
>>
>> It does record the path at which the tracked content is, of course. But
>> it tracks the history of content, not that of paths.
>>
>> What you see in the diff above is merely one way to interpret the
>> history of the content. Saying
>>
>> renamed:  a -> b
>> new file: Makefile
>>
>> leads to the same content at the same paths (with the proper new file
>> content).
>>
>> By default, diff tries to interpret content history in terms of renames
>> and copies when possible, in order to help users. Sometimes this fails -
>> while still being correct, it confuses them ;)
> 
> Sure, that's one way to look at it, but I disagree. You give the user
> the way to tell the system the intention of which file moves where,
> but internally this information is lost and "guessed" incorrectly.
> 
> hg seems to do this correctly, the same commands with 'hg diff --git'
> at the end show:
> 
> diff --git a/Makefile b/Makefile
> new file mode 100644
> diff --git a/a b/b
> rename from a
> rename to b
> 
>  Thomas
> 

Maybe you can re-read what I wrote above, keeping in mind the first line:

git tracks content, not paths.

That explains everything, really.

Michael