4

git diff-tree indicates a file was deleted but when I run git log, it doesn't show anything.

To wit:

> git diff-tree --stat --summary 1990ca669fe..00de228dcdc -- t/tests.conf
t/tests.conf |    9 ---------
1 files changed, 0 insertions(+), 9 deletions(-)
delete mode 100644 t/tests.conf

And when I run:

> git log 1990ca669fe..00de228dcdc -- t/tests.conf

I get no output.

Any idea I on how I can track down why git thinks this file has been deleted since it's also causing problems in a merge I'm trying?

Update

This doesn't produce any output either:

> git log 1990ca669fe...00de228dcdc -- t/tests.conf

And the commits are reachable:

 > git rev-list 00de228dcdc | grep 1990ca669fe
  1990ca669fe9ec94d215945388458daba8d94747
Tyrone Slothrop
  • 40,787
  • 3
  • 17
  • 8
  • This was a tough nut to crack. I'm boggled as well. Waiting for VonC to clear things up :D – rtn May 02 '11 at 23:21
  • ha..glad I'm not alone. it's kind of driving me nuts. – Tyrone Slothrop May 03 '11 at 00:32
  • @Magnus @Tyrone I suspect because of the meaning of '..' which might be different between diff-tree and log: see http://stackoverflow.com/questions/2539040/not-able-to-think-of-a-case-where-git-diff-master-lab-and-git-diff-master-lab or http://stackoverflow.com/questions/850607/difference-in-git-log-origin-master-vs-git-log-origin-master – VonC May 03 '11 at 02:26
  • I was suspecting that as well, but couldn't crack it. Thanks. – rtn May 03 '11 at 06:38
  • Or for an answer with graphical representations of the difference between '..' in `git log` and `git diff`, see http://stackoverflow.com/questions/5256249/git-diff-doesnt-show-enough/5257065#5257065 – Mark Longair May 03 '11 at 10:24

1 Answers1

8

My guess is that 1990ca669fe and 00de228dcdc have divergent histories (neither is reachable from the other). You probably want this command (three dots, not two):

git log 1990ca669fe...00de228dcdc -- t/tests.conf

It will show the commits from each side of the history (instead of just the commits leading to 00de228dcdc).

In short:
To see the “stuff” from both sides (A and B), use git diff A..B and git log A...B.
To only get “stuff” from the second side (B), use git diff A...B and git log A..B.

That is quite an unfortunate UI wart.


The “log” commands are about reviewing the history graph (commit “ranges”, or sets of commits).
They interpret A..B as equivalent to B --not A (i.e. the set of commits that are reachable from B but not from A). A...B is equivalent to A B --not $(git merge-base --all A B) (i.e. the set of commits from both sides since they diverged; this is called the “symmetric difference of A and B”).

The “diff” commands are about comparing two particular trees or blobs (just the “endpoints”, (mostly) not about any history that might connect them). They interpret A..B as equivalent to A B (i.e. just another way to directly specify the endpoints for a diff operation). A...B is equivalent to
$(git merge-base A B)..B or $(git merge-base A B) B (this is history-aware, thus the “mostly” above).

From git-diff(1):

"diff" is about comparing two endpoints, not ranges, and the range notations ("<commit>..<commit>" and "<commit>...<commit>") do not mean a range as defined in the "SPECIFYING RANGES" section in gitrevisions(7).


Let us consider git log A..B and git diff A..B for two different kinds of history.

If A and B are linearly related (illustrated below),

---1---2---A---3---4---B

then you will see similar output for both types of commands. git log A..B will show the commits 3, 4 and B. git diff A..B will show the difference between the trees referenced by commits A and B; this diff will be equivalent to accumulating the patches represented by commits 3, 4, and B.

The three-dot versions are uninteresting since the merge base of A and B is A itself. For “log” commands, A...B means A B --not $(git merge-base --all A B), which ends up being
A B --not A, which means B --not A, which is the same as A..B. For “diff” commands, A...B means $(git merge-base A B)..B, which ends up being A..B.

However, if A and B have divergent histories (neither is reachable from the other; illustrated below),

---1---D---3---4---A
        \
         5---6---B

then the diff will include changes from both branches while the log will only show the commits made to one of the branches. git log A..B will show commits 5, 6, and A. git diff A..B will show the difference between the trees referenced by commits A and B; this diff will include the patches represented by commits 5, 6, and B as well as by 3, 4, and A.

The three-dot variants are interesting in this case. For “log” commands, A...B means
A B --not $(git merge-base --all A B), which ends up meaning A B --not D, which eventually expands to the set 3, 4, A, 5, 6, B (i.e. the commits that are reachable from A or B but not both). For “diff” commands, A...B means $(git merge-base A B)..B, which ends up being D..B (i.e. all the changes made on “B’s side” since B diverged from A).

Chris Johnsen
  • 214,407
  • 26
  • 209
  • 186
  • Crystal clear: `"diff" is about comparing two endpoints, not ranges, and the range notations (".." and "...") do not mean a range` - splendid explanation Chris – sehe May 03 '11 at 05:54
  • Thanks. This is a great answer so I'm upvoting. Unfortunately the triple dot in git log doesn't produce any output either. There's something weird doing on in my repo. I think the culprit is a reverted merge but I can't see anything in the logs where t/tests.conf is actually deleted so I'm confused as to why git thinks this is deleted when I do a diff on those commits. – Tyrone Slothrop May 03 '11 at 18:52