Skip to content

commit.diff with parent vs NULL_TREE not coherent #732

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
LeResKP opened this issue Feb 28, 2018 · 2 comments
Open

commit.diff with parent vs NULL_TREE not coherent #732

LeResKP opened this issue Feb 28, 2018 · 2 comments

Comments

@LeResKP
Copy link
Contributor

LeResKP commented Feb 28, 2018

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 LeResKP changed the title commit.diff with parent vs NULL_TREE commit.diff with parent vs NULL_TREE not coherent Feb 28, 2018
@Byron
Copy link
Member

Byron commented Mar 17, 2018

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.

@ishepard
Copy link
Contributor

ishepard commented Jun 5, 2018

@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

----------

tobru pushed a commit to projectsyn/commodore that referenced this issue Dec 17, 2019
Computing the diff in git.stage_all failed on an empty repository
because the changes were always diffed against the 'master' branch.
However an empty repository doesn't have a master branch.

This commit implements diffing the changes against the Git empty tree,
which is represented as the sha1 hash of the C string "tree 0"
(including the null byte terminator).  This change allows Commodore to
correctly diff changes against an empty git repository.

See also:
* gitpython-developers/GitPython#732 (comment)
* https://stackoverflow.com/q/9765453
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants