Browse Source

merge-recursive: give less scary messages when merge did not start

When unpack_trees() three-way merge logic is called from merge-recursive
and finds that local changes are going to be clobbered, its plumbing level
messages were given as errors first, and then the merge driver added even
more scary message "fatal: merging of trees <a long object name> and
<another long object name> failed".

This is most often encountered by new CVS/SVN migrants who are used to
start a merge from a dirty work tree.  The saddest part is that the merge
refused to run to prevent _any_ damage from being done to your work tree
when these messages are given, but the messages look a lot more scarier
than the conflicted case where the user needs to resolve them.

Replace the plumbing level messages so that they talk about what it is
protecting the user from, and end the messages with "Aborting." so that it
becomes clear that the command did not do any harm.

The final "merging of trees failed" message is superfluous, unless you are
interested in debugging the merge-recursive itself.  Squelch the current
die() message by default, but allow it to help people who debug git with
verbosity level 4 or greater.

Unless there is some bug, an inner merge that does not touch working tree
should not trigger any such error, so emit the current die() message when
we see an error return from it while running the inner merge, too.  It
would also help people who debug git.

We could later add instructions on how to recover (i.e. "stash changes
away or commit on a side branch and retry") instead of the silent
exit(128) I have in this patch, and then use Peff's advice.* mechanism to
squelch it (e.g. "advice.mergeindirtytree"), but they are separate topics.

Tested-by: Nanako Shiraishi <nanako3@lavabit.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Junio C Hamano 16 years ago
parent
commit
fadd069d03
  1. 19
      merge-recursive.c

19
merge-recursive.c

@ -170,6 +170,18 @@ static int git_merge_trees(int index_only,
int rc; int rc;
struct tree_desc t[3]; struct tree_desc t[3];
struct unpack_trees_options opts; struct unpack_trees_options opts;
static const struct unpack_trees_error_msgs msgs = {
/* would_overwrite */
"Your local changes to '%s' would be overwritten by merge. Aborting.",
/* not_uptodate_file */
"Your local changes to '%s' would be overwritten by merge. Aborting.",
/* not_uptodate_dir */
"Updating '%s' would lose untracked files in it. Aborting.",
/* would_lose_untracked */
"Untracked working tree file '%s' would be %s by merge. Aborting",
/* bind_overlap -- will not happen here */
NULL,
};


memset(&opts, 0, sizeof(opts)); memset(&opts, 0, sizeof(opts));
if (index_only) if (index_only)
@ -181,6 +193,7 @@ static int git_merge_trees(int index_only,
opts.fn = threeway_merge; opts.fn = threeway_merge;
opts.src_index = &the_index; opts.src_index = &the_index;
opts.dst_index = &the_index; opts.dst_index = &the_index;
opts.msgs = msgs;


init_tree_desc_from_tree(t+0, common); init_tree_desc_from_tree(t+0, common);
init_tree_desc_from_tree(t+1, head); init_tree_desc_from_tree(t+1, head);
@ -1188,10 +1201,14 @@ int merge_trees(struct merge_options *o,


code = git_merge_trees(o->call_depth, common, head, merge); code = git_merge_trees(o->call_depth, common, head, merge);


if (code != 0) if (code != 0) {
if (show(o, 4) || o->call_depth)
die("merging of trees %s and %s failed", die("merging of trees %s and %s failed",
sha1_to_hex(head->object.sha1), sha1_to_hex(head->object.sha1),
sha1_to_hex(merge->object.sha1)); sha1_to_hex(merge->object.sha1));
else
exit(128);
}


if (unmerged_cache()) { if (unmerged_cache()) {
struct string_list *entries, *re_head, *re_merge; struct string_list *entries, *re_head, *re_merge;

Loading…
Cancel
Save