diff mbox series

[1/7] merge-ort: mark a few more conflict messages as omittable

Message ID df6e2774f1a5560a598dd8b46131bc6b0a261d4a.1630376800.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Add a new --remerge-diff capability to show & log | expand

Commit Message

Elijah Newren Aug. 31, 2021, 2:26 a.m. UTC
From: Elijah Newren <newren@gmail.com>

path_msg() has the ability to mark messages as omittable when recording
conflict messages in an in-tree file.  This conflict message file will
then be shown by diffing the merge-created tree to the actual merge
commit that is created.  While all the messages touched in this commit
are very useful when trying to create a merge initially, early use with
the --remerge-diff feature (the only user of this omittable conflict
message capability), suggests that the particular messages marked in
this commit are just noise when trying to see what changes users made to
create a merge commit.  Mark them as omittable.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Junio C Hamano Aug. 31, 2021, 9:06 p.m. UTC | #1
"Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Elijah Newren <newren@gmail.com>
>
> path_msg() has the ability to mark messages as omittable when recording
> conflict messages in an in-tree file.  This conflict message file will
> then be shown by diffing the merge-created tree to the actual merge
> commit that is created.  While all the messages touched in this commit
> are very useful when trying to create a merge initially, early use with
> the --remerge-diff feature (the only user of this omittable conflict
> message capability), suggests that the particular messages marked in
> this commit are just noise when trying to see what changes users made to
> create a merge commit.  Mark them as omittable.

Sorry for asking something that may be obvious, but if you recreate
an automated and potentially conflicting merge in-core, in order to
then compare the recorded merge result, is there *any* message that
is worth showing while doing the first step, and where in the output
do users see them?
Elijah Newren Sept. 1, 2021, 12:03 a.m. UTC | #2
On Tue, Aug 31, 2021 at 2:06 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Elijah Newren <newren@gmail.com>
> >
> > path_msg() has the ability to mark messages as omittable when recording
> > conflict messages in an in-tree file.  This conflict message file will
> > then be shown by diffing the merge-created tree to the actual merge
> > commit that is created.  While all the messages touched in this commit
> > are very useful when trying to create a merge initially, early use with
> > the --remerge-diff feature (the only user of this omittable conflict
> > message capability), suggests that the particular messages marked in
> > this commit are just noise when trying to see what changes users made to
> > create a merge commit.  Mark them as omittable.
>
> Sorry for asking something that may be obvious

No, it's not obvious.  I had a hard time figuring out the right way to
split up this series and order the patches in part because so many
little pieces are needed before I can show the solution.  So some of
this comes from the later patches, but let me see if I can motivate
the issue and solution I picked a bit more right here.

> but if you recreate
> an automated and potentially conflicting merge in-core, in order to
> then compare the recorded merge result, is there *any* message that
> is worth showing while doing the first step,

Yes, absolutely.  While three-way *content* conflicts are easily
representable within a file in the working tree using conflict
markers, *non-content* conflicts are usually not easily representable
in such a fashion.  For example, a rename/delete conflict will not
result in any conflict markers, and will result in the renamed version
of the file being left in the working tree; the only way you know
there is a conflict for that file is either because of the stage in
the index or the the message that is printed to the terminal:

    CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s.

But relying on higher order stages in the index and messages printed
to the terminal present a bit of a problem for --remerge-diff; as
described, it ignores both those sources of input.  Here's a few other
conflict types that face similar issues:

  * modify/delete conflicts
  * failure to merge submodule
  * directory rename detection (i.e. new file added to old directory
that other side renamed; which directory should file end up in?)
  * distinct types of files (e.g. regular file and symlink) located at
the same path
  * rename/rename conflicts

In all these cases (and some others), relying on a diff of "what the
working directory looks like at the end of a merge" to "the tree
recorded in the merge commit" does not convey enough (if any)
information about the above types of conflicts.

> and where in the output do users see them?

For --remerge-diff, I chose to handle the fact that the working
directory didn't naturally have enough information, by augmenting the
working directory with additional information.  So, for example, if
there was a file named `dir/my.file` that had a modify/delete conflict
(and the user who did the real merge edited that file a bit as part of
conflict resolution), then I would also add a `dir/my.fil
e.conflict_msg` file whose contents are

"""
== Conflict notices for my.file ==
CONFLICT (modify/delete): dir/my.file deleted in HASH1 (SHORT
SUMMARY1) and modified in HASH2 (SHORT SUMMARY 2).  Version HASH2
(SHORT SUMMARY2) of  dir/my.file left in tree.
"""

Creating this file means you see something like this in the
remerge-diff (note there are diffs for two files, with the synthetic
file appearing just before the file it has messages about):

diff --git a/dir/my.fil e.conflict_msg b/dir/my.fil e.conflict_msg
deleted file mode 100644
index 2bd215a32f06..000000000000
--- a/dir/my.fil e.conflict_msg
+++ /dev/null
@@ -1,2 +0,0 @@
-== Conflict notices for my.file ==
-CONFLICT (modify/delete): dir/my.file deleted in HASH1 (SHORT
SUMMARY1) and modified in HASH2 (SHORT SUMMARY 2).  Version HASH2
(SHORT SUMMARY2) of  dir/my.file left in tree.
diff --git a/dir/my.file b/dir/my.file
index 09c78c725a3b..79f9d1fb7611 100644
--- a/dir/my.file
+++ b/dir/my.file
@@ -950,15 +912,15 @@ int my_func(struct stuff *data,
                                        rq->timeline,
                                        rq);

-               old_func(data, 1);
+               new_func("for funsies", data, VALID);
                obj->value = 8;
                obj->read_attempts = 0;
        } else {
-               err = old_func(data, 0);
+               err = new_func("for funsies", data, INVALID);
                if (unlikely(err))
                        return err;

-               another_old_func(data, obj->value);
+               another_new_func(data, obj->value, INVALID);
                obj->value++;
        }
        obj->read_attempts += 1;


The `dir/my.fil e.conflict_msg` file is definitely slightly weird, but
any solution here would be.  I think it's fairly intuitive what is
meant.  No one has commented on this choice in the 9+ months it's been
in use internally by ~50 users (even with -p implying --remerge-diff
automatically to make it more likely people have used this option), so
either it really is intuitive, or it doesn't come up much.  It could
well be the latter.
Junio C Hamano Sept. 1, 2021, 5:19 p.m. UTC | #3
Elijah Newren <newren@gmail.com> writes:

> Creating this file means you see something like this in the
> remerge-diff (note there are diffs for two files, with the synthetic
> file appearing just before the file it has messages about):
>
> diff --git a/dir/my.fil e.conflict_msg b/dir/my.fil e.conflict_msg
> deleted file mode 100644
> index 2bd215a32f06..000000000000
> --- a/dir/my.fil e.conflict_msg
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -== Conflict notices for my.file ==
> -CONFLICT (modify/delete): dir/my.file deleted in HASH1 (SHORT
> SUMMARY1) and modified in HASH2 (SHORT SUMMARY 2).  Version HASH2
> (SHORT SUMMARY2) of  dir/my.file left in tree.

I do not know if my reaction should be "Cute" or "Yuck" ;-)

Hopefully nobody uses .conflict_msg as a suffix for their files.
diff mbox series

Patch

diff --git a/merge-ort.c b/merge-ort.c
index 515dc39b7f6..4dbf0a477af 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2409,7 +2409,7 @@  static void apply_directory_rename_modifications(struct merge_options *opt,
 		 */
 		ci->path_conflict = 1;
 		if (pair->status == 'A')
-			path_msg(opt, new_path, 0,
+			path_msg(opt, new_path, 1,
 				 _("CONFLICT (file location): %s added in %s "
 				   "inside a directory that was renamed in %s, "
 				   "suggesting it should perhaps be moved to "
@@ -2417,7 +2417,7 @@  static void apply_directory_rename_modifications(struct merge_options *opt,
 				 old_path, branch_with_new_path,
 				 branch_with_dir_rename, new_path);
 		else
-			path_msg(opt, new_path, 0,
+			path_msg(opt, new_path, 1,
 				 _("CONFLICT (file location): %s renamed to %s "
 				   "in %s, inside a directory that was renamed "
 				   "in %s, suggesting it should perhaps be "
@@ -3814,7 +3814,7 @@  static void process_entry(struct merge_options *opt,
 				reason = _("add/add");
 			if (S_ISGITLINK(merged_file.mode))
 				reason = _("submodule");
-			path_msg(opt, path, 0,
+			path_msg(opt, path, 1,
 				 _("CONFLICT (%s): Merge conflict in %s"),
 				 reason, path);
 		}