Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git diff-tree shows a delete but there's no delete in git log

Tags:

git

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
like image 995
Tyrone Slothrop Avatar asked Feb 24 '23 08:02

Tyrone Slothrop


1 Answers

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).

like image 143
Chris Johnsen Avatar answered Feb 27 '23 07:02

Chris Johnsen