diff mbox series

[v5,1/1] mergetool: add automerge configuration

Message ID 20201223045358.100754-2-felipe.contreras@gmail.com (mailing list archive)
State New, archived
Headers show
Series mergetool: remove unconflicted lines | expand

Commit Message

Felipe Contreras Dec. 23, 2020, 4:53 a.m. UTC
The purpose of mergetools is to resolve conflicts when git cannot
automatically do so.

In order to do that git has added markers in the specific areas that
need resolving, which the user must manually fix. The tool is supposed
to help with that.

However, by passing the original BASE, LOCAL, and REMOTE files, many
changes without conflict are presented to the user when in fact nothing
needs to be done for those.

We can fix that by propagating the final version of the file with the
automatic merge to all the panes of the mergetool (BASE, LOCAL, and
REMOTE), and only make them differ on the places where there are actual
conflicts.

As most people will want the new behavior, we enable it by default.
Users that do not want the new behavior can set the new configuration
mergetool.autoMerge to false.

See Seth House's blog post [1] for the idea, and the rationale.

[1] https://www.eseth.org/2020/mergetools.html

Original-idea-by: Seth House <seth@eseth.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Documentation/config/mergetool.txt |  3 +++
 git-mergetool.sh                   | 17 +++++++++++++++++
 t/t7610-mergetool.sh               | 18 ++++++++++++++++++
 3 files changed, 38 insertions(+)

Comments

Junio C Hamano Dec. 23, 2020, 1:34 p.m. UTC | #1
Felipe Contreras <felipe.contreras@gmail.com> writes:

> +auto_merge () {
> +	git merge-file --diff3 --marker-size=7 -q -p "$LOCAL" "$BASE" "$REMOTE" >"$DIFF3"
> +	if test -s "$DIFF3"
> +	then

We do not want to ignore the exit status from the command.  IOW, I
think the above wants to be rather

	if git merge-file ... >"$DIFF3" &&
	   test -s "$DIFF3"
	then
		...

to catch a merge-file that writes halfway and then crashes (doing
the same check in different ways are probably possible, of course)

> +		sed -e '/^<<<<<<< /,/^||||||| /d' -e '/^=======\r\?$/,/^>>>>>>> /d' "$DIFF3" >"$BASE"

Does everybody's sed take "\?" and interprets it as zero-or-one?
POSIX uses BRE and it doesn't like \? as far as I recall, and "-E"
to force ERE is a GNUism.

> +		sed -e '/^||||||| /,/^>>>>>>> /d' -e '/^<<<<<<< /d' "$DIFF3" >"$LOCAL"
> +		sed -e '/^<<<<<<< /,/^=======\r\?$/d' -e '/^>>>>>>> /d' "$DIFF3" >"$REMOTE"

I'd feel safer if these resulting $BASE, $LOCAL and $REMOTE are
validated to be conflict-marker free (i.e. '^\([<|=>]\)\1\1\1\1\1\1'
does not appear) to make sure there was no funny virtual ancestor
that records a conflicted recursive merge result confused our logic.

When we see an unfortunate sign that it happened, we can revert the
automerge and let the tool handle the original input.

> +	fi
> +	rm -- "$DIFF3"
> +}
> +

"$DIFF3" is always created (unless shell redirection into it fails),
so "rm --" would be fine in practice, I guess, but "rm -f --" would
not hurt.

> +	DIFF3="$MERGETOOL_TMPDIR/${BASE}_DIFF3_$$$ext"

$MERGETOOL_TMPDIR is either "mktemp -d -t "git-mergetool-XXXXXX" or
".".  Also, we liberally pass "$DIFF3" to "sed" as an argument and
assume that the command would take it as a filename and not an
option.

For the above reason, "rm --", while it is not wrong per-se, can be
just a simple "rm", as there is no funny leading letters in "$DIFF3"
that requires disambiguation.
Felipe Contreras Dec. 23, 2020, 2:23 p.m. UTC | #2
Junio C Hamano wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > +auto_merge () {
> > +	git merge-file --diff3 --marker-size=7 -q -p "$LOCAL" "$BASE" "$REMOTE" >"$DIFF3"
> > +	if test -s "$DIFF3"
> > +	then
> 
> We do not want to ignore the exit status from the command.  IOW, I
> think the above wants to be rather
> 
> 	if git merge-file ... >"$DIFF3" &&
> 	   test -s "$DIFF3"
> 	then
> 		...

That doesn't work.

"git merge-file" always returns non-zero status when it succeeds (it's
the number of conflicts generated).

> > +		sed -e '/^<<<<<<< /,/^||||||| /d' -e '/^=======\r\?$/,/^>>>>>>> /d' "$DIFF3" >"$BASE"
> 
> Does everybody's sed take "\?" and interprets it as zero-or-one?

I don't know.

> POSIX uses BRE and it doesn't like \? as far as I recall, and "-E"
> to force ERE is a GNUism.

Another possibility is \s\*. It's less specific though.

> > +		sed -e '/^||||||| /,/^>>>>>>> /d' -e '/^<<<<<<< /d' "$DIFF3" >"$LOCAL"
> > +		sed -e '/^<<<<<<< /,/^=======\r\?$/d' -e '/^>>>>>>> /d' "$DIFF3" >"$REMOTE"
> 
> I'd feel safer if these resulting $BASE, $LOCAL and $REMOTE are
> validated to be conflict-marker free (i.e. '^\([<|=>]\)\1\1\1\1\1\1'
> does not appear) to make sure there was no funny virtual ancestor
> that records a conflicted recursive merge result confused our logic.
> 
> When we see an unfortunate sign that it happened, we can revert the
> automerge and let the tool handle the original input.

What if the original file does have these markers?

Which is probably something we should be checking beforehand and not
attempt an automerge in those cases.

Or we could add the --base option to "git merge-file" so we don't have
to do that work by hand.

> > +	fi
> > +	rm -- "$DIFF3"
> > +}
> > +
> 
> "$DIFF3" is always created (unless shell redirection into it fails),
> so "rm --" would be fine in practice, I guess, but "rm -f --" would
> not hurt.

I just did the same as below:

  rm -- "$BACKUP"

> > +	DIFF3="$MERGETOOL_TMPDIR/${BASE}_DIFF3_$$$ext"
> 
> $MERGETOOL_TMPDIR is either "mktemp -d -t "git-mergetool-XXXXXX" or
> ".".  Also, we liberally pass "$DIFF3" to "sed" as an argument and
> assume that the command would take it as a filename and not an
> option.
> 
> For the above reason, "rm --", while it is not wrong per-se, can be
> just a simple "rm", as there is no funny leading letters in "$DIFF3"
> that requires disambiguation.

Other parts of the file do this:

  rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP"

I'm just following what the script already does.

Cheers.
Junio C Hamano Dec. 23, 2020, 8:21 p.m. UTC | #3
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Junio C Hamano wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> > +auto_merge () {
>> > +	git merge-file --diff3 --marker-size=7 -q -p "$LOCAL" "$BASE" "$REMOTE" >"$DIFF3"
>> > +	if test -s "$DIFF3"
>> > +	then
>> 
>> We do not want to ignore the exit status from the command.  IOW, I
>> think the above wants to be rather
>> 
>> 	if git merge-file ... >"$DIFF3" &&
>> 	   test -s "$DIFF3"
>> 	then
>> 		...
>
> That doesn't work.
>
> "git merge-file" always returns non-zero status when it succeeds (it's
> the number of conflicts generated).

Ah, I forgot about that one.  I think "the number of conflicts" was
a UI mistake (the original that it mimics is "merge" from RCS suite,
which uses 1 and 2 for "conflicts" and "trouble") but we know we
will get conflicts, so it is wrong to expect success from the
command.  Deliberately ignoring the return status is the right thing
to do.

> What if the original file does have these markers?
>
> Which is probably something we should be checking beforehand and not
> attempt an automerge in those cases.

Yes, that is a much better approach to avoid unnecessary work.

When we made the conflict marker length configurable, we were hoping
that we no longer have to worry about the cases where payload files
(original or ours or theirs) have lines that are confusingly similar
to the conflict markers, but because we are interfacing external tools
that are unaware of the facility, it probably would not help us in
this case all that much.

FWIW, we use a fiarly large size for our own files in t/ and
Documentation/ directories ourselves, and it does help topic branch
merges somewhat frequently.
Felipe Contreras Dec. 24, 2020, 12:14 a.m. UTC | #4
Junio C Hamano wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Junio C Hamano wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> 
> >> > +auto_merge () {
> >> > +	git merge-file --diff3 --marker-size=7 -q -p "$LOCAL" "$BASE" "$REMOTE" >"$DIFF3"
> >> > +	if test -s "$DIFF3"
> >> > +	then
> >> 
> >> We do not want to ignore the exit status from the command.  IOW, I
> >> think the above wants to be rather
> >> 
> >> 	if git merge-file ... >"$DIFF3" &&
> >> 	   test -s "$DIFF3"
> >> 	then
> >> 		...
> >
> > That doesn't work.
> >
> > "git merge-file" always returns non-zero status when it succeeds (it's
> > the number of conflicts generated).
> 
> Ah, I forgot about that one.  I think "the number of conflicts" was
> a UI mistake (the original that it mimics is "merge" from RCS suite,
> which uses 1 and 2 for "conflicts" and "trouble") but we know we
> will get conflicts, so it is wrong to expect success from the
> command.  Deliberately ignoring the return status is the right thing
> to do.

I agree. My bet is that nobody is checking the return status of "git
merge-file" to find out the number of conflicts. Plus, how can you check
the difference between 255 conflicts and error -1?

But that's the situation we are in now.

> > What if the original file does have these markers?
> >
> > Which is probably something we should be checking beforehand and not
> > attempt an automerge in those cases.
> 
> Yes, that is a much better approach to avoid unnecessary work.
> 
> When we made the conflict marker length configurable, we were hoping
> that we no longer have to worry about the cases where payload files
> (original or ours or theirs) have lines that are confusingly similar
> to the conflict markers, but because we are interfacing external tools
> that are unaware of the facility, it probably would not help us in
> this case all that much.
> 
> FWIW, we use a fiarly large size for our own files in t/ and
> Documentation/ directories ourselves, and it does help topic branch
> merges somewhat frequently.

We could do something like --marker-size=13 to minimize the chances of
that happening.

In that case I would prefer '/^<\{13\} /' (to avoid too many
characters). I see those regexes used elsewhere in git, but I don't know
how portable that is.

If we wanted to make sure none of those markers remain it's not enough
to check for '^[<|=>]{13}', what follows up should be a space, or some
delimiter, not another < for example. So maybe '^[<|=>]{13}[^<|=>]'?

So, do we want those three things?

 1. A non-standard marker-size
 2. Check beforehand the existence of those markers and disable
    automerge
 3. Check afterwards the existence of those markers and disable
    automerge

Cheers.
Junio C Hamano Dec. 24, 2020, 12:32 a.m. UTC | #5
Felipe Contreras <felipe.contreras@gmail.com> writes:

>> Ah, I forgot about that one.  I think "the number of conflicts" was
>> a UI mistake (the original that it mimics is "merge" from RCS suite,
>> which uses 1 and 2 for "conflicts" and "trouble") but we know we
>> will get conflicts, so it is wrong to expect success from the
>> command.  Deliberately ignoring the return status is the right thing
>> to do.
>
> I agree. My bet is that nobody is checking the return status of "git
> merge-file" to find out the number of conflicts. Plus, how can you check
> the difference between 255 conflicts and error -1?

Yup, I already mentioned UI mistake so you do not have to repeat it
to consume more bandwidth.  We're in agreement already.

> We could do something like --marker-size=13 to minimize the chances of
> that happening.
>
> In that case I would prefer '/^<\{13\} /' (to avoid too many
> characters). I see those regexes used elsewhere in git, but I don't know
> how portable that is.

If it is used elsewhere with "sed", then that would be OK, but if it
is not with "sed" but with "grep", that's quite a different story.

> So, do we want those three things?
>
>  1. A non-standard marker-size
>  2. Check beforehand the existence of those markers and disable
>     automerge
>  3. Check afterwards the existence of those markers and disable
>     automerge

I do not think 3 is needed if we do 2 and I do not think 1 would
particularly be useful *UNLESS* the code consults with the attribute
system to see what marker size the path uses to avoid crashing with
the non-standard marker-size the path already uses.

So the easiest would be not to do anything for now, with a note
about known limitations in the doc.  The second easiest would be to
do 2. alone.  We could do 1. to be more complete but I tend to think
that it is better to leave it as #leftoverbits.
Felipe Contreras Dec. 24, 2020, 1:36 a.m. UTC | #6
Junio C Hamano wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> >> Ah, I forgot about that one.  I think "the number of conflicts" was
> >> a UI mistake (the original that it mimics is "merge" from RCS suite,
> >> which uses 1 and 2 for "conflicts" and "trouble") but we know we
> >> will get conflicts, so it is wrong to expect success from the
> >> command.  Deliberately ignoring the return status is the right thing
> >> to do.
> >
> > I agree. My bet is that nobody is checking the return status of "git
> > merge-file" to find out the number of conflicts. Plus, how can you check
> > the difference between 255 conflicts and error -1?
> 
> Yup, I already mentioned UI mistake so you do not have to repeat

You said it was a UI mistake, not me. I am a different mind than yours.

This [1] is the first time *you* communicated it was a UI mistake.

This [2] is the first time *I* communicated it was a UI mistake.

I communicated that fact after you, so I did not repeat anything,
because I hadn't said that before. *You* did, not *me*.

> it to consume more bandwidth.

This is what is consuming bandwidth.

Not me stating *for the first time* that I agree what you just stated.

You could have skipped what I said *for the first time*, if you didn't
find it particularly interesting, and that would have saved bandwidth.

> > We could do something like --marker-size=13 to minimize the chances of
> > that happening.
> >
> > In that case I would prefer '/^<\{13\} /' (to avoid too many
> > characters). I see those regexes used elsewhere in git, but I don't know
> > how portable that is.
> 
> If it is used elsewhere with "sed", then that would be OK, but if it
> is not with "sed" but with "grep", that's quite a different story.

In t/t3427-rebase-subtree.sh there is:

  sed -e "s%\([0-9a-f]\{40\} \)files_subtree/%\1%"

Not sure if that counts. There's other places in the tests.

However, I don't see the point if the marker-size is a low enough number, like 7.

> > So, do we want those three things?
> >
> >  1. A non-standard marker-size
> >  2. Check beforehand the existence of those markers and disable
> >     automerge
> >  3. Check afterwards the existence of those markers and disable
> >     automerge
> 
> I do not think 3 is needed if we do 2 and I do not think 1 would
> particularly be useful *UNLESS* the code consults with the attribute
> system to see what marker size the path uses to avoid crashing with
> the non-standard marker-size the path already uses.

But what is more likely? a) That the marker-size is 7 (the default), or
b) that the marker-size is not the default, but that there's a
marker-size attribute *and* the value is precisely 13?

I think a) is way more likely than b).

> So the easiest would be not to do anything for now, with a note
> about known limitations in the doc.  The second easiest would be to
> do 2. alone.  We could do 1. to be more complete but I tend to think
> that it is better to leave it as #leftoverbits.

OK. I think 1. is low-hanging fruit, but I'm fine with not doing
anything, or trying 2.

I don't think 2. would be that hard, so I will try that before
re-rolling the series.

(unless somebody replies to my other pending arguments)

Cheers.

[1] https://lore.kernel.org/git/xmqqblek8e94.fsf@gitster.c.googlers.com/
[2] https://lore.kernel.org/git/5fe3dd62e12f8_7855a2081f@natae.notmuch/
Junio C Hamano Dec. 24, 2020, 6:17 a.m. UTC | #7
Felipe Contreras <felipe.contreras@gmail.com> writes:

>> Yup, I already mentioned UI mistake so you do not have to repeat
>
> You said it was a UI mistake, not me. I am a different mind than yours.

Yes, but the point is that I do not need to nor particularly want to
hear your opinion on the behaviour of "git merge-file".  I know (and
others reading the thread on the list also know) that the exit code
of the command is misdesigned already.

> I communicated that fact after you, so I did not repeat anything,
> because I hadn't said that before. *You* did, not *me*.

Again, please realize that on list discussion is a team effort to
come up together a better design of a shared solution.  And if you
already know that (I don't read your mind ;-), please act like you
do, too.

Thanks.
Felipe Contreras Dec. 24, 2020, 3:59 p.m. UTC | #8
Junio C Hamano wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> >> Yup, I already mentioned UI mistake so you do not have to repeat
> >
> > You said it was a UI mistake, not me. I am a different mind than yours.
> 
> Yes, but the point is that I do not need to nor particularly want to
> hear your opinion on the behaviour of "git merge-file".

Then disregard the comment.

> I know (and others reading the thread on the list also know) that the
> exit code of the command is misdesigned already.

Unless you can read minds, you don't know that.

And even if you do, I don't know what you know. I can't read your mind.

Plus, they can disregard the comment as well.

> > I communicated that fact after you, so I did not repeat anything,
> > because I hadn't said that before. *You* did, not *me*.
> 
> Again, please realize that on list discussion is a team effort to
> come up together a better design of a shared solution.

Which is why agreement in a team with different minds and different
viewpoints is important.

Just to show a few instances of Jeff King telling you he agrees with
you:

 1. "I agree it's not all that useful in that example" [1]. 16 Dec 2020
 2. "I agree with the current definition" [2]. 18 Dec 2020 (same thread)
 3. "I agree the two should behave the same" [3]. 18 Dec 2020 (same
    mail)

The fact that you value Jeff King's agreement and don't care what some
other members in the community think, is a personal vale judgement, and
doesn't necessarily mean the viewpoints of such community members are
objectively worthless.

Cheers.

[1] https://lore.kernel.org/git/X9pUc2HXUr3+WHbR@coredump.intra.peff.net/
[2] https://lore.kernel.org/git/X9xJ6BHM9VY0%2FyLs@coredump.intra.peff.net/
[3] https://lore.kernel.org/git/X9xJ6BHM9VY0%2FyLs@coredump.intra.peff.net/
Junio C Hamano Dec. 24, 2020, 10:32 p.m. UTC | #9
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Junio C Hamano wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> >> Yup, I already mentioned UI mistake so you do not have to repeat
>> >
>> > You said it was a UI mistake, not me. I am a different mind than yours.
>> 
>> Yes, but the point is that I do not need to nor particularly want to
>> hear your opinion on the behaviour of "git merge-file".
>
>> I know (and others reading the thread on the list also know) that the
>> exit code of the command is misdesigned already.
>
> Unless you can read minds, you don't know that.

Actually I do, because they heard from me already ;-).  If this were
the case where our messages crossed, perhaps, but in this case yours
was a response to my message.

>> Again, please realize that on list discussion is a team effort to
>> come up together a better design of a shared solution.
>
> Which is why agreement in a team with different minds and different
> viewpoints is important.

It is not like opinions on all points are important.  Whether the
exit code from merge-file is or is not a UI mistake does NOT have
any influence on what we were discussing.  My opinion is that exit
code from merge-file is a UI mistake, but even if you disagree with
that, that would not change the conclusion we already reached that
the code should ignore its exit status, like you originally wrote.

I am already trying to ignore your opinions on things that do not
matter in the context of this project, as you told me earlier ;-)
But just like patches, messages are written only once but read by
many people, so I'd always aim for reducing noise at the source.

Anyway, happy holidays and pleasant new year to you and to
everybody.
Felipe Contreras Dec. 27, 2020, 6:01 p.m. UTC | #10
Junio C Hamano wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Junio C Hamano wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> 
> >> >> Yup, I already mentioned UI mistake so you do not have to repeat
> >> >
> >> > You said it was a UI mistake, not me. I am a different mind than yours.
> >> 
> >> Yes, but the point is that I do not need to nor particularly want to
> >> hear your opinion on the behaviour of "git merge-file".
> >
> >> I know (and others reading the thread on the list also know) that the
> >> exit code of the command is misdesigned already.
> >
> > Unless you can read minds, you don't know that.
> 
> Actually I do, because they heard from me already ;-).

They heard that you *think* it's a UI mistake.

The fact that you think something is a mistake doesn't necessarily mean
it's actually a mistake, and other community members might think
otherwise.

You do not dictate what others on the list know.

> >> Again, please realize that on list discussion is a team effort to
> >> come up together a better design of a shared solution.
> >
> > Which is why agreement in a team with different minds and different
> > viewpoints is important.
> 
> It is not like opinions on all points are important.  Whether the
> exit code from merge-file is or is not a UI mistake does NOT have
> any influence on what we were discussing.

Which is why I initially did not express such an opinion.

But you did, presumably you had some reason to do so, so I simply
did the same and expressed mine.

> I am already trying to ignore your opinions on things that do not
> matter in the context of this project, as you told me earlier ;-)
> But just like patches, messages are written only once but read by
> many people, so I'd always aim for reducing noise at the source.

What you consider noise others might not.

Good writers say you should not assume what your readers know.

Yes, some readers might think exactly like you do, and they don't need
what you consider obvious information. But for every person that
thinks exactly like you, there are dozens that don't, and it's those you
should keep in mind.

Most people err on the side of not providing enough information to the
minds dissimilar to theirs.

This is called the curse of knowledge [1].

I try not to do that.

> Anyway, happy holidays and pleasant new year to you and to
> everybody.

Same to you.

Cheers.

[1] https://en.wikipedia.org/wiki/Curse_of_knowledge
diff mbox series

Patch

diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt
index 16a27443a3..7ce6d0d3ac 100644
--- a/Documentation/config/mergetool.txt
+++ b/Documentation/config/mergetool.txt
@@ -61,3 +61,6 @@  mergetool.writeToTemp::
 
 mergetool.prompt::
 	Prompt before each invocation of the merge resolution program.
+
+mergetool.autoMerge::
+	Remove lines without conflicts from all the files. Defaults to `true`.
diff --git a/git-mergetool.sh b/git-mergetool.sh
index e3f6d543fb..f4db0cac8d 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -239,6 +239,17 @@  checkout_staged_file () {
 	fi
 }
 
+auto_merge () {
+	git merge-file --diff3 --marker-size=7 -q -p "$LOCAL" "$BASE" "$REMOTE" >"$DIFF3"
+	if test -s "$DIFF3"
+	then
+		sed -e '/^<<<<<<< /,/^||||||| /d' -e '/^=======\r\?$/,/^>>>>>>> /d' "$DIFF3" >"$BASE"
+		sed -e '/^||||||| /,/^>>>>>>> /d' -e '/^<<<<<<< /d' "$DIFF3" >"$LOCAL"
+		sed -e '/^<<<<<<< /,/^=======\r\?$/d' -e '/^>>>>>>> /d' "$DIFF3" >"$REMOTE"
+	fi
+	rm -- "$DIFF3"
+}
+
 merge_file () {
 	MERGED="$1"
 
@@ -274,6 +285,7 @@  merge_file () {
 		BASE=${BASE##*/}
 	fi
 
+	DIFF3="$MERGETOOL_TMPDIR/${BASE}_DIFF3_$$$ext"
 	BACKUP="$MERGETOOL_TMPDIR/${BASE}_BACKUP_$$$ext"
 	LOCAL="$MERGETOOL_TMPDIR/${BASE}_LOCAL_$$$ext"
 	REMOTE="$MERGETOOL_TMPDIR/${BASE}_REMOTE_$$$ext"
@@ -322,6 +334,11 @@  merge_file () {
 	checkout_staged_file 2 "$MERGED" "$LOCAL"
 	checkout_staged_file 3 "$MERGED" "$REMOTE"
 
+	if test "$(git config --bool mergetool.autoMerge)" != "false"
+	then
+		auto_merge
+	fi
+
 	if test -z "$local_mode" || test -z "$remote_mode"
 	then
 		echo "Deleted merge conflict for '$MERGED':"
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 70afdd06fa..ccabd04823 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -828,4 +828,22 @@  test_expect_success 'mergetool -Oorder-file is honored' '
 	test_cmp expect actual
 '
 
+test_expect_success 'mergetool automerge' '
+	test_config mergetool.automerge true &&
+	test_when_finished "git reset --hard" &&
+	git checkout -b test${test_count}_b master &&
+	test_write_lines >file1 base "" a &&
+	git commit -a -m "base" &&
+	test_write_lines >file1 base "" c &&
+	git commit -a -m "remote update" &&
+	git checkout -b test${test_count}_a HEAD~ &&
+	test_write_lines >file1 local "" b &&
+	git commit -a -m "local update" &&
+	test_must_fail git merge test${test_count}_b &&
+	yes "" | git mergetool file1 &&
+	test_write_lines >expect local "" c &&
+	test_cmp expect file1 &&
+	git commit -m "test resolved with mergetool"
+'
+
 test_done