Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use three way diff for diff

Tags:

git

Another S.O. question shows how to configure git to use a three way diff for merge conflicts.

Is it possible to set up this three way style as the default for a standard diff operation? If I request a diff between versions where there is a common root (that isn't just one of the versions), changes from the common root will be shown in the diff.

like image 738
Benjohn Avatar asked Oct 30 '15 16:10

Benjohn


People also ask

How does a 3-way diff work?

A three-way merge is where two changesets to one base file are merged as they are applied, as opposed to applying one, then merging the result with the other. For example, having two changes where a line is added in the same place could be interpreted as two additions, not a change of one line.

Why do we do 3-way merge?

The reason it is called a 3-way merge is because the Merge Commit is based on 3 different commits. The common ancestor of our branches, in this case commit number C3. This commit contains code before we diverge into different branches.

How do I use the araxis merge tool?

Locate and select Compare.exe in the Merge installation folder (typically something like C:\Program Files\Araxis\Araxis Merge ). Click the Open button. The full path to the Merge Compare.exe utility should now be shown in the Choose application to compare files entry field. Click OK to dismiss the Preferences dialog.


1 Answers

I'm afraid the answer is no.

The ratonale for this is that no matter how you specify the arguments when calling git diff, it always considers just two entities (blobs or trees (most of the time inferred from the commits referring to them)). In other words, that's by design: git diff considers separate objects and does not do any history traversal. To cite the git diff manual page:

For a more complete list of ways to spell <commit>, see "SPECIFYING REVISIONS" section in gitrevisions(7). However, "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).

On the other hand, with a suitable shell, you should be able to do that thing yourself. Say, given two commits, rev1 and rev2, you could use

git-diff3() {
  local rev1="$1" rev2="$2"
  diff3 <(git show "$rev1") \
        <(git show $(git merge-base "$rev1" "$rev2")) \
        <(git show "$rev2")
}

in a shell which understands <(...) (e.g. bash).

This function requires massaging to make it more useful/less fragile but I hope you get the idea.

like image 141
kostix Avatar answered Sep 22 '22 03:09

kostix