How to use Difftool to show all changes between two revisions avoiding changes made in merges?
I can use git log to show that changes with this command:
git log --no-merges -p firstrevinbranch..lastrevinbranch
But git log only shows changesets, not the file, so I can read the context properly.
Is there any way to use difftool to do this and show changes between revisions buy avoiding merges? I mean, in a scneario like that:
A---B---C---D topic
/ / \
E---F---G---H---I master
I want to show with kdiff only changes made in commits A,B and D, avoiding C so it's a merge commit.
Thank you very much.
The short answer is "you can't".
The long answer is that you can, but only by first creating new commits that have different changes in them. In other words, rather than looking at what you do have now, you can make something else, and then look at that. The amount of value you get by doing this will depend in part on how well you do when you make the something-else.
Here are the facts. (Whether these are happy facts or sad facts depends on your point of view.) A commit, in Git, stores a snapshot. It does not store changes. The snapshot itself is literally an archive. No existing snapshot can ever be changed, so it's a read-only archive.
When you use
git difftool
withkdiff3
, you:kdiff3
on these files, perhaps having it compare them to your current working tree (one option) or to another extracted archive (the other option).So, given your example:
you can get
git difftool
to extract the snapshot from commitA
, or from commitB
, orC
orD
or ... up throughI
. You can have it extract any other commit as well, and then runkdiff3
on the two extractions, or you can use the first extraction to runkdiff3
on that and whatever is currently in your working tree.To see what might be in a hypothetical snapshot formed by taking the snapshot in
B
, then making the changes to that snapshot achieved by:C
toD
; thenB
you will literally have to execute steps 1 and 2 first. The result can be stored anywhere you like: a temporary directory, a whole new repository, or a commit (temporary or permanent) that you make in this repository. Git can assist you with the making a new commit. The value you get from actually making such a commit is, well, up to you, but the easy way to do that is:
check out commit
B
, creating a new branch (as temporary or permanent as you like):cherry-pick commit
D
:The result of all this is a new commit
J
:The difference between the snapshot in
J
and that inB
is the same as, or similar to, the difference between the snapshot inD
and that inC
. For this reason you might want to call commitJ
by some other name, such asD'
, but it doesn't really matter what you call it; it's a new commit, containing an archive of the result of the cherry-pick.