While working on a tool that determines relevant history for a given commit from a previous export, I found a rather odd behavior in git log and I can't seem to pin down what's happening. I'm hoping someone can help explain the behavior.
I've created the following commit graph, and I have two separate workspaces in the same repo. Workspace A has a single file updated in every single commit listed except for E and I which are simple merges (for example git merge bar
created commit I). Workspace B, on the other hand, has only had files changed in commits A and L.
When I run git log --name-only --oneline -- workspaceA
I get commit 'I' listed, but there are no files affected:
b7faf96 (HEAD -\> main) Commit I
a3c265e Commit H
workspaceA/H
e03be40 (bar) Commit L
workspaceA/L
7ead348 Commit G
workspaceA/G
7b80d8d (tag: workspaceA-2020.0.2.0, baz) Commit B
workspaceA/B
d383bfa Commit F
workspaceA/F
6d2b8a4 (tag: workspaceB-2020.0.1.0, tag: workspaceA-2020.0.1.0) Commit A
workspaceA/A
...
Note that this list contains Commit 'I' but it has no files listed under the commit.
Now, when I run git log --name-only --oneline -- workspaceB
I get a list that doesn't contain commit 'I' at all:
e03be40 (bar) Commit L
workspaceB/L
6d2b8a4 (tag: workspaceB-2020.0.1.0, tag: workspaceA-2020.0.1.0) Commit A
workspaceB/A
...
My problem is that there isn't any consistency in whether commit 'I' shows up, even though none of the files were actually changed during the merge which created commit 'I'. Can anyone explain why this is happening?
This doesn't meet my expectations because I can't see why commit 'I' only shows up when filtering for one folder and not the other, even though the merge involves changes to both folders as seen in my screenshot.
CodePudding user response:
The reason this happens is because Git is showing you the list of commits that represent a new state from the point of view of the path filter you specified.
From the POV of workspaceA
, there are changes to something in that folder in both sides of the merge. Commit I
has two parents: H
and L
. The merge-base
of H
and L
is commit B
, and there is at least one change to something in workspaceA
between B
and H
, and also between B
and L
. This means that commit I
has a new state for workspaceA
even though the commit itself doesn't contain any changes.
Notice this is not the case for workspaceB
. There are no changes between B
and H
, and there is a change between B
and L
. So the merge commit I
will not have a state change compared to L
, which has already been listed.
CodePudding user response:
By default, git log
completely hides diffs for merge commits.
Add one of the diff-merges
options to see what files were considered : I'd advise --cc
, you may also try -c
or -m
.
From git help log :
DIFF FORMATTING :
[...]
--diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc)
Specify diff format to be used for merge commits. Default is
off
unless--first-parent
is in use, in which casefirst-parent
is the default.
Shorthand for options are :
-m
for--diff-merges=on
or--diff-merges=m
-c
forcombined
--cc
fordense-combined