git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* 4-way diff (base,ours,theirs,merged) to review merge results
@ 2012-02-26  3:55 Neal Kreitzinger
  2012-02-26  8:12 ` Junio C Hamano
  2012-02-26  9:05 ` Junio C Hamano
  0 siblings, 2 replies; 3+ messages in thread
From: Neal Kreitzinger @ 2012-02-26  3:55 UTC (permalink / raw)
  To: git

Combined diff only tells you what the merge result auto-resolved (with 
rerere turned off and no merge-conflicts) in comparison to "ours" and 
"theirs".  That only tells you what "ours" and "theirs" *had*, not what they 
*did* (or were trying to do).  You need the merge-base version to see what 
"ours" and "theirs" did.  Seeing what "ours" and "theirs" did will 
much-better tell you if "merged" did-the-right-thing or not.  What is the 
best way to display a 4-way diff of merge-base, "ours", "theirs", and 
"merged" after a merge completes so you can review the "merged" results for 
correctness?

Before I try writing a script to dump the object-contents of the merge-base, 
"ours", "theirs", and "merged" versions of the-file-in-question to 
work-files and then feed them to a 4-way diff for review, I would like to 
see if someone already has a script or better-idea for this, or if git has 
something more straight-forward that already does-this-for-you.

Reason for this:
If "ours" has line-x and "theirs" does not have line-x, and "merged" does 
have line-x you still have a mystery on your hands:

(Combined diff)
ours:  has line-x
theirs (master):  does not have line-x
merged:  has line-x
merge-base (older master):  *may-or-may-not* have line-x
conclusion:  I'm not very sure if "merged" should have line-x or not...

Based on the combined-diff only, I don't know if "merged" should have line-x 
or not because I don't know if "ours" *added* line-x to the merge-base or if 
"theirs" *removed* line-x from the merge-base.  IOW, if "theirs" is master 
and "ours" is way-behind master then I pretty-much know I probably need to 
take "theirs" because it has the latest-stuff.  However, I don't know if 
"theirs" took line-x out of master (and "ours" just has line-x because its 
old), or if line-x was never in master and "ours" really-needed to add it. 
Having merge-base context allows for more accurate conclusions like this:

ours:  has line-x
theirs (master):  does not have line-x
merged:  has line-x
merge-base (older master):  has line-x
conclusion:  I should probably take line-x out of "merged"

ours:  has line-x
theirs (master):  does not have line-x
merged:  has line-x
merge-base:  does not have line-x
conclusion:  I should probably keep line-x in "merged"

Thanks in advance for you feedback.

v/r,
neal 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: 4-way diff (base,ours,theirs,merged) to review merge results
  2012-02-26  3:55 4-way diff (base,ours,theirs,merged) to review merge results Neal Kreitzinger
@ 2012-02-26  8:12 ` Junio C Hamano
  2012-02-26  9:05 ` Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Junio C Hamano @ 2012-02-26  8:12 UTC (permalink / raw)
  To: Neal Kreitzinger; +Cc: git

"Neal Kreitzinger" <neal@rsss.com> writes:

> (Combined diff)
> ours:  has line-x
> theirs (master):  does not have line-x
> merged:  has line-x
> merge-base (older master):  *may-or-may-not* have line-x
> conclusion:  I'm not very sure if "merged" should have line-x or not...

When I need this information to resolve a merge in an area of the code
that I am not very familiar with, the first thing I do is this:

  $ git merge $other
  $ git diff
  ... yikes, that is a complex conflict!

  $ git checkout --conflict=diff3 $the_path_with_difficult_conflict
  $ git diff

The output will also show the lines from the merge base.

The default style of showing the conflict we use is called the "merge"
style (it originally came from the "merge" program of the RCS suite), and
it only gives the two sides without the base version.  It is sufficient
when the person who is making the merge is familiar with the baseline
history of the code (e.g. in a contributor-to-integrator pull based
workflow, especially when contributors are encouraged to keep their topics
focused and short). The "diff3" style that also gives the base version is
needed less often in such a setting. That, and also the resulting output
is much shorter, is the reason why "merge" style is the default.

When the person who is making the merge is not very familiar with the
baseline history (e.g. when using Git as an improved CVS and a contributor
pulls the updated upstream into his history), however, "diff3" style may
be more often helpful---as you mentioned, "merge" style requires that you
know your code well enough to either already know or be able to guess how
the version in the merge base looked like, but by definition, pulling the
updated upstream into your work will pull more stuff (because many other
people are working on the code on the other side) than pulling one topic
from a contributor into the integrator tree, so there may be more need to
see the version from the merge base in such a workflow.

By setting the configuration variable "merge.conflictstyle" to "diff3",
you would get the base version by default whenever there is a conflict.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: 4-way diff (base,ours,theirs,merged) to review merge results
  2012-02-26  3:55 4-way diff (base,ours,theirs,merged) to review merge results Neal Kreitzinger
  2012-02-26  8:12 ` Junio C Hamano
@ 2012-02-26  9:05 ` Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Junio C Hamano @ 2012-02-26  9:05 UTC (permalink / raw)
  To: Neal Kreitzinger; +Cc: git

"Neal Kreitzinger" <neal@rsss.com> writes:

> ....  What is the 
> best way to display a 4-way diff of merge-base, "ours", "theirs", and 
> "merged" after a merge completes so you can review the "merged" results for 
> correctness?

Ahh, sorry.  While everything I wrote in my previous reply is correct with
respect to what happens _during_ a merge until you resolve it, I did not
realize that you were asking how to view a merge _after_ it is made.

For a two-parent merge $M, "git show --cc $M" runs a three-way diff
between $M (merge result), $M^1 (the first parent) and $M^2 (the other
parent) and the combined diff it shows is equivalent to:

  $ git diff --cc $M $M^1 $M^2

Notice the order of parameters. Unlike a normal "diff A B" to ask the
command to explain how the state B is reached from state A, you give the
result $M and ask the command to explain how it was reached from other
states.

So in a similar way, running

  $ git diff --cc $M $M^1 $M^2 $(git merge-base $M^1 $M^2)

should show a combined patch that explains the state at $M relative to the
states recorded in its parents and the merge base.

I've never tried it myself, though, as I never needed such an operation.

You can try a trivial example with 4d9e079, which merges 583c389 ec7ff5b
and has conflicts in cache.h

$ git show 4d9e079 -- cache.h
Output omitted; you can see it is the same as the next one for yourself.

$ git diff --cc 4d9e079 583c389 ec7ff5b -- cache.h
diff --cc cache.h
index 3a8e125,24732e6..422c5cf
--- a/cache.h
+++ b/cache.h
@@@ -1177,7 -1176,7 +1177,8 @@@ extern void setup_pager(void)
  extern const char *pager_program;
  extern int pager_in_use(void);
  extern int pager_use_color;
 +extern int term_columns(void);
+ extern int decimal_width(int);
  
  extern const char *editor_program;
  extern const char *askpass_program;

One side adds term_columns, the other side adds decimal_width.

$ git diff --cc 4d9e079 583c389 ec7ff5b \
    $(git merge-base 583c389 ec7ff5b) -- cache.h
diff --cc cache.h
index 3a8e125,24732e6,9bd8c2d..422c5cf
--- a/cache.h
+++ b/cache.h
@@@@ -1177,7 -1176,7 -1176,6 +1177,8 @@@@ extern void setup_pager(void)
   extern const char *pager_program;
   extern int pager_in_use(void);
   extern int pager_use_color;
 ++extern int term_columns(void);
+ +extern int decimal_width(int);
   
   extern const char *editor_program;
   extern const char *askpass_program;

The third column is a diff between $M and $(git merge-base $M^1 $M^2); the
resulting two new lines are indeed shown as additions against the merge
base.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-02-26  9:06 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-26  3:55 4-way diff (base,ours,theirs,merged) to review merge results Neal Kreitzinger
2012-02-26  8:12 ` Junio C Hamano
2012-02-26  9:05 ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).