I have a branch with a function definition missing but the function is still being used causing a crash. The function definition must have been deleted during a merge. I have do
This leads me to believe that 'git log -p' doesn't show merge changes? How can I get this functionality?
You are correct: by default, git log -p
shows you the merge commit, but does not even attempt to show a diff for it.
As odradek wrote in a comment, adding the -c
option will make git log
show combined diffs. You may also use --cc
(note two dashes for --cc
, vs one dash for -c
) which also shows a combined diff, or -m
, which effectively splits the merge for diff purposes, and shows one diff per parent, against that parent.
These same three options can be used with git show
. For whatever reason, though, git show
defaults to --cc
while git log
defaults to nothing at all.
The difference between the three options is clear only with some merges, and it's a bit tricky to show them. We can, however, say one thing pretty clearly: any combined diff shows only files that differ from all parents. That is, both git show -c
and git show --cc
trim what's shown to try to be helpful. (The --cc
form may trim more than -c
, depending on what there is that can be shown. I do not have a handy example of this, though.)
For example, consider commit 3e5c63943d35be1804d302c0393affc4916c3dc3 in the Git repository for Git. This is a merge (with parents c13c783...
and 20690b2...
, and if we run two separate git diff
commands, we can see that, as compared to its first parent, only two files change:
$ git diff --name-status 3e5c639^1 3e5c639
M builtin/remote.c
M t/t5505-remote.sh
but as compared to its second parent, many files (including those same two) change:
$ git diff --name-status 3e5c639^2 3e5c639 | expand
M .gitignore
M .mailmap
M Documentation/Makefile
A Documentation/RelNotes/2.12.0.txt
M Documentation/SubmittingPatches
A Documentation/asciidoctor-extensions.rb
M Documentation/blame-options.txt
M Documentation/cat-texi.perl
M Documentation/config.txt
M Documentation/diff-config.txt
[snipped here - but the same two files do appear in the 339-entry list]
If I run git show --cc
on this, I get no diff listing at all; if I run git show -c
on it, I get a diff listing for builtin/remote.c
and for t/t5505-remote.sh
.
If I run git show -m
on this, I get instead two separate git diff
listings. Neither is a "combined diff". The first starts with:
commit 3e5c63943d35be1804d302c0393affc4916c3dc3 (from
c13c783c9d3d7d3eff937b7bf3642d2a7fe32644)
and shows just the first two files. The second starts with:
commit 3e5c63943d35be1804d302c0393affc4916c3dc3 (from
20690b213975ad3e9b1bc851f434d818bd2d1de9)
and shows all 339 files.
Using -m
is the Really Big Hammer, but you are left with a lot of sorting to do through a lot of pieces. Using --cc
or -c
is usually sufficient.
(Something else that may help, when looking for this sort of change with git log -p
, is to add --full-history
to make sure that git log
follows both branches down each merge. This is only required if you are doing history simplification by adding -- <path>
options.)
This leads me to believe that '
git log -p
' doesn't show merge changes?
It does, with Git 2.31 (Q1 2021): "git log"(man) learned a new --diff-merges=<how>
option.
See commit af04d8f, commit 1d24509, commit e58142a, commit 8efd2ef, commit b5ffa9e, commit 388091f, commit 5071c75, commit a6d19ec, commit 5733b20, commit 8c0ba52, commit 255a4da, commit 3d2b5f2, commit a6e66af, commit d9b1bc6, commit 1a2c4d8, commit 6fc944d, commit ec315c6, commit 14c14b4, commit e121b4b, commit 0c627f5, commit 3291eea, commit 3b6c17b, commit 09322b1, commit 564a4fc, commit 4f54544, commit 7acf0d0, commit 18f0947, commit a37eec6, commit 3d4fd94, commit 027c478, commit 299a663, commit 891e417 (21 Dec 2020) by Sergey Organov (sorganov).
(Merged by Junio C Hamano -- gitster -- in commit aac006a, 05 Feb 2021)
diff-merges: implement new values for
--diff-merges
Signed-off-by: Sergey Organov
We first implement new options as exact synonyms for their original counterparts, to get all the infrastructure right, and keep functional improvements for later commits.
The following values are implemented:
--diff-merges= old equivalent first|first-parent = --first-parent (only format implications) sep|separate = -m comb|combined = -c dense| dense-combined = `--cc`
diff-merges: add old mnemonic counterparts to
--diff-merges
Signed-off-by: Sergey Organov
This adds
--diff-merges={m|c|cc}
values that match mnemonics of old options, for those who are used to them.Note that, say,
--diff-meres=cc
behaves differently than--cc
, as the latter implies-p
and therefore enables diffs for all the commits, while the former enables output of diffs for merge commits only.
diff-merges: add '
--diff-merges=1
' as synonym for 'first-parent
'Signed-off-by: Sergey Organov
As we now have
--diff-merges={m|c|cc}
, add--diff-merges=1
as synonym for --diff-merges=first-parent, to have shorter mnemonics for it as well.
doc/git-show: include --diff-merges description
Signed-off-by: Sergey Organov
Move description of
--diff-merges
option fromgit-log.txt
todiff-options.txt
so that it is included in the git-show(man) help.
diff-options
now includes in its man page:
ifdef::git-log[]
--diff-merges=(off|none|first-parent|1|separate|m|combined|c|dense-combined|cc)
--no-diff-merges
Specify diff format to be used for merge commits. Default is {diff-merges-default} unless
--first-parent
is in use, in which casefirst-parent
is the default.
--diff-merges=(off|none):
--no-diff-merges:
Disable output of diffs for merge commits. Useful to override implied value.
--diff-merges=first-parent:
--diff-merges=1:
This option makes merge commits show the full diff with respect to the first parent only.
--diff-merges=separate:
--diff-merges=m:
-m:
This makes merge commits show the full diff with respect to each of the parents.
Separate log entry and diff is generated for each parent.
-m
doesn't produce any output without-p
.
--diff-merges=combined:
--diff-merges=c:
-c:
With this option, diff output for a merge commit shows the differences from each of the parents to the merge result simultaneously instead of showing pairwise diff between a parent and the result one at a time.
Furthermore, it lists only files which were modified from all parents.
-c
implies-p
.
--diff-merges=dense-combined:
--diff-merges=cc:
--cc:
With this option the output produced by
--diff-merges=combined
is further compressed by omitting uninteresting hunks whose contents in the parents have only two variants and the merge result picks one of them without modification.--cc
implies-p
.
--combined-all-paths
This flag causes combined diffs (used for merge commits) to list the name of the file from all parents. It thus only has effect when
--diff-merges=[dense-]combined
is in use, and is likely only useful if filename changes are detected (i.e. when either rename or copy detection have been requested). endif::git-log[]
git log
now includes in its man page:
:diff-merges-default:
off
git show
now includes in its man page:
DIFF FORMATTING
The options below can be used to change the way
git show
generates diff output.
git show
now includes in its man page:
:diff-merges-default:
dense-combined
This is based on the work from Git 2.29 (Q4 2020), formally documented:
See commit 5fbb4bc, commit 9a6d515, commit 6cea104, commit 6f2e02a, commit 9ab89a2, commit 6fae74b, commit eed5332 (29 Jul 2020) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit eca8c62, 17 Aug 2020)
doc/git-log: clarify handling of merge commit diffs
Signed-off-by: Jeff King
It can be surprising that
git-log
doesn't show any diff for merge commits by default.
Arguably "--cc
" would be a reasonable default, but it's very expensive (which is why we turn it on for "git show"(man) but not for "git log
").Let's at least document the current behavior, including the recent "
--first-parent implies -m
" case
git log
now includes in its man page:
Note that unless one of
-c
,--cc
, or-m
is given, merge commits will never show a diff, even if a diff format like--patch
is selected, nor will they match search options like-S
.The exception is when
--first-parent
is in use, in which merges are treated like normal single-parent commits (this can be overridden by providing a combined-diff option or with--no-diff-merges
).
And you also have:
To countermand the implicit "
-m
" option when the "--first-parent
" option is used with "git log"(man) , we added the "--[no-]diff-merges
" option in thejk/log-fp-implies-m
topic.To leave the door open to allow the "
--diff-merges
" option to take values that instructs how patches for merge commits should be computed (e.g. "cc
"? "-p
against first parent?"), redefine "--diff-merges
" to take non-optional value, and implement "off
" that means the same thing as "--no-diff-merges
".
See commit 298889d, commit 405a2fd, commit 6501580 (06 Aug 2020) by Sergey Organov (sorganov).
(Merged by Junio C Hamano -- gitster -- in commit a555b51, 17 Aug 2020)
doc/git-log: describe
--diff-merges=off
Signed-off-by: Sergey Organov
git log
now includes in its man page:
--diff-merges=off
--no-diff-merges
Disable output of diffs for merge commits (default).
Useful to override-m
,-c
, or--cc
.