GitPython icon indicating copy to clipboard operation
GitPython copied to clipboard

commit.diff with parent vs NULL_TREE not coherent

Open LeResKP opened this issue 7 years ago • 2 comments

After adding a new file I made a diff vs NULL_TREE, I have the expected behaviour change_type == 'A'. When making the diff of the same commit vs the parent I get change_type == 'D', I think the sha keys are not correctly passed.

Perhaps I'm wrong and I missed something... If you confirm the issue, I can fix it!

Here is an example to reproduce the issue:

test.py

import git

repo = git.Repo('.')

print('Diff with NULL_TREE')
diffs = repo.head.commit.diff(git.NULL_TREE)

for diff in diffs:
    print(diff)
    print('type', diff.change_type)
    print()
    print('-' * 10)


print()
print('*' * 10)
print()

print('Diff with parent')
diffs = repo.head.commit.diff(repo.head.commit.parents[0])

for diff in diffs:
    print(diff)
    print('type', diff.change_type)
    print()
    print('-' * 10)

test.sh

#!/bin/sh
mkdir test
cd test
git init
touch A
git add .
git commit -m "add A"

touch B
git add .
git commit -m "add B"

python ../test.py

cd ..
rm -rf test

Here is the result

tmp $ sh test.sh
Initialized empty Git repository in /tmp/test/.git/
[master (root-commit) 779b71f] add A
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 A
[master d27e0b1] add B
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 B
Diff with NULL_TREE
B
=======================================================
lhs: None
rhs: 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
file added in rhs
('type', u'A')
()
----------

**********

Diff with parent
B
=======================================================
lhs: 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
rhs: None
file deleted in rhs
('type', u'D')
()
----------

LeResKP avatar Feb 28 '18 07:02 LeResKP

Thanks for making it so easy to follow along! A great issue! I agree that the behavior seems to be inconsistent, even though I believe the behavior seen with the parent is correct. It answers the question of 'what do you have to do to get from state A to state B?', which is delete the previously added file.

Thus I believe some order is wrong when using the special 'NULL_TREE', which is what I would fix. I would very much welcome a PR which accomplishes this.

Byron avatar Mar 17 '18 08:03 Byron

@Byron indeed, this is not a bug. To get the correct DIFF, one has always to do: git diff PARENT -> CURRENT

so NULL_TREE -> CURRENT.

The correct solution is:

import git

repo = git.Repo('.')

print('Diff with NULL_TREE')
# this is the null tree, not sure why git.NULL_TREE doesn't work
parent = repo.tree('4b825dc642cb6eb9a060e54bf8d69288fbee4904')
diffs = parent.diff(repo.head.commit.tree)

for diff in diffs:
    print(diff)
    print('type', diff.change_type)
    print()
    print('-' * 10)


print()
print('*' * 10)
print()

print('Diff with parent')
## IMPORTANT: this is inverted, parents vs head commit
diffs = repo.head.commit.parents[0].diff(repo.head.commit)

for diff in diffs:
    print(diff)
    print('type', diff.change_type)
    print()
    print('-' * 10)

and the output is:

Initialized empty Git repository in /private/tmp/temp/test/.git/
[master (root-commit) 4bac140] add A
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 A
[master a4ceb50] add B
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 B
Diff with NULL_TREE
A
=======================================================
lhs: None
rhs: 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
file added in rhs
type A

----------
B
=======================================================
lhs: None
rhs: 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
file added in rhs
type A

----------

**********

Diff with parent
B
=======================================================
lhs: None
rhs: 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
file added in rhs
type A

----------

ishepard avatar Jun 05 '18 13:06 ishepard