Skip to content

Instantly share code, notes, and snippets.

@dmalikov
Created April 30, 2015 15:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmalikov/9c7413c765ab80a00811 to your computer and use it in GitHub Desktop.
Save dmalikov/9c7413c765ab80a00811 to your computer and use it in GitHub Desktop.
`git-diff` != `git-diff-tree`?

Suppose there is a commit C which have a single parent commit P.

Let's say that TC and TP are the corresponding tree objects.

Why git diff P C is not always equal to git diff-tree TP TC -p?


Why they should be equal?

According to a git protocol specification, each commit object is pointing on only one tree objects. Different commit objects could use the same tree object, but not vice-versa.

Any example?

For instance, let's take this public repo : git@github.com:dmalikov/dotfiles.git.

Here is some commit object:

>> git cat-file -p 67019a5daef556ef5c3e2bea4f425d9a5044bc44
tree 1e9c97a5f0da406f4e74d02897393606e902408d
parent 435f7e6a78d5c5797c0997c1ad73f11d38d89d7a
author Dmitry Malikov <malikov.d.y@gmail.com> 1374867081 +0400
committer Dmitry Malikov <malikov.d.y@gmail.com> 1374867754 +0400

Vifm: cue2tracks mapping

Here is parent commit:

>> git cat-file -p 435f7e6a78d5c5797c0997c1ad73f11d38d89d7a
tree eb00b6ee310bda76280c515c5bd698e3247d3416
parent 00a1c0f55cd6c9eaa6621b0c7799c56d6bf76df5
author Dmitry Malikov <malikov.d.y@gmail.com> 1374831285 +0400
committer Dmitry Malikov <malikov.d.y@gmail.com> 1374834097 +0400

Vim: correct tabs for js and eruby

Commits' diff:

>> git diff 435f7e6a78d5c5797c0997c1ad73f11d38d89d7a 67019a5daef556ef5c3e2bea4f425d9a5044bc44 --stat
 configs/vifm/vifmrc | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

Trees' diff:

>> git diff-tree eb00b6ee310bda76280c515c5bd698e3247d3416 1e9c97a5f0da406f4e74d02897393606e902408d --stat
 configs/vifm/vifmrc | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

Unfortunately they're are different. Let's take a closer look again

>> git diff 435f7e6a78d5c5797c0997c1ad73f11d38d89d7a 67019a5daef556ef5c3e2bea4f425d9a5044bc44
diff --git a/configs/vifm/vifmrc b/configs/vifm/vifmrc
index 95b540d..a41bd54 100644
--- a/configs/vifm/vifmrc
+++ b/configs/vifm/vifmrc
@@ -167,14 +167,15 @@ filetype *.ssh FUSE_MOUNT2|sshfs %PARAM %DESTINATION_DIR
 set vifminfo=bookmarks

 " Sample mappings
+nmap ,c :!cue2tracks -RF<CR>

-nmap s :shell<cr>
-nmap S :sort<cr>
-nmap w :view<cr>
-nmap o :!gvim --remote-tab-silent %f<cr>
-nmap O :!gvim %f<cr>
-" open file in the background using its default program
-nmap gb :file &<cr>l
+" nmap s :shell<cr>
+" nmap S :sort<cr>
+" nmap w :view<cr>
+" nmap o :!gvim --remote-tab-silent %f<cr>
+" nmap O :!gvim %f<cr>
+" " open file in the background using its default program
+" nmap gb :file &<cr>l

 nmap <f3> :!less %f<cr>
 nmap <f4> :edit<cr>

And a trees' analogue:

>> git diff-tree eb00b6ee310bda76280c515c5bd698e3247d3416 1e9c97a5f0da406f4e74d02897393606e902408d -p
diff --git a/configs/vifm/vifmrc b/configs/vifm/vifmrc
index 95b540d..a41bd54 100644
--- a/configs/vifm/vifmrc
+++ b/configs/vifm/vifmrc
@@ -167,14 +167,15 @@ filetype *.ssh FUSE_MOUNT2|sshfs %PARAM %DESTINATION_DIR
 set vifminfo=bookmarks

 " Sample mappings
-
-nmap s :shell<cr>
-nmap S :sort<cr>
-nmap w :view<cr>
-nmap o :!gvim --remote-tab-silent %f<cr>
-nmap O :!gvim %f<cr>
-" open file in the background using its default program
-nmap gb :file &<cr>l
+nmap ,c :!cue2tracks -RF<CR>
+
+" nmap s :shell<cr>
+" nmap S :sort<cr>
+" nmap w :view<cr>
+" nmap o :!gvim --remote-tab-silent %f<cr>
+" nmap O :!gvim %f<cr>
+" " open file in the background using its default program
+" nmap gb :file &<cr>l

 nmap <f3> :!less %f<cr>
 nmap <f4> :edit<cr>

So what we have here is some kind of different difference strategies used for calculating diff.

How often this issue occurs?

For a repository mentioned above there are 10 commits with the issue out of 735 commits.


Finally

What is the difference between diff and diff-tree commands?

@dbolkensteyn
Copy link

Good news 8 years later: the output in both cases is now identical, at least with Git version 2.40.1.

I was expected differences in cases of merge commits, but not with a single parent commit. That bug must have been fixed I guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment