threads / discuss / 64140

[QUESTION] mergetool environment variables

Subject: [QUESTION] mergetool environment variables

## tl;dr

8 messages between Sep 12, 2025 and Sep 15, 2025.

replies: 7people: 5as markdown or json

rsbecker@nexbridge.com· Sep 12, 2025, 20:16 UTC · lore

I am trying to integrate a custom mergetool with a shell wrapper. What I get from the online help is the following description referring to the command and environment variables.

mergetool.<tool>.cmd Specify the command to invoke the specified merge tool. The specified command is evaluated in shell with the following variables available: BASE is the name of a temporary file containing the common base of the files to be merged, if available; LOCAL is the name of a temporary file containing the contents of the file on the current branch; REMOTE is the name of a temporary file containing the contents of the file from the branch being merged; MERGED contains the name of the file to which the merge tool should write the results of a successful merge.

When I try to use this from a shell, simply with: #!/bin/sh env exit 1

the described environment variables: BASE, LOCAL, REMOTE, and MERGED, are not present.

The history is trivial, but has a 1 line conflict after a git merge. The file is called a, with two lines at the parent commit and the middle line changed in both branches being merged. There are correct temp files in the directory while the shell script is being run. The merged file looks as follows:

Hello <<<<<<< HEAD Ours ======= Theirs

>>>>>>> Incoming
World

This applies to git 2.45.1 in cygwin and 2.51.0 on NonStop. There are no upstreams. Is this the problem?

Any thoughts on this?

Thanks, Randall

-- Brief whoami: NonStop&UNIX developer since approximately UNIX(421664400) NonStop(211288444200000000) -- In real life, I talk too much.

Johannes Sixt· Sep 13, 2025, 07:04 UTC · re: rsbecker@nexbridge.com · lore

Re: [QUESTION] mergetool environment variables

Am 12.09.25 um 22:16 schrieb rsbecker@nexbridge.com:
Show 8 quoted lines
> I am trying to integrate a custom mergetool with a shell wrapper.
> What I get from the online help is the following description referring
> to the command and environment variables.
> 
> mergetool.<tool>.cmd 
> Specify the command to invoke the specified merge tool.
> The specified command is evaluated in shell with the
> following variables available: BASE is the name of a
Take note: this talks about "variables", not "environment variables".
Show 16 quoted lines
> temporary file containing the common base of the files
> to be merged, if available; LOCAL is the name of a
> temporary file containing the contents of the file on
> the current branch; REMOTE is the name of a temporary
> file containing the contents of the file from the branch
> being merged; MERGED contains the name of the file
> to which the merge tool should write the results of a
> successful merge.
> 
> When I try to use this from a shell, simply with:
> #!/bin/sh
> env
> exit 1
> 
> the described environment variables: BASE, LOCAL,
> REMOTE, and MERGED, are not present.

Look at the scripts in the directory mergetools/ and note that they are only (large) shell code fragements without a shbang line. They are not even executable.

-- Hannes
rsbecker@nexbridge.com· Sep 13, 2025, 14:42 UTC · re: Johannes Sixt · lore

RE: [QUESTION] mergetool environment variables

On September 13, 2025 3:05 AM, Johannes Sixt wrote:
Show 29 quoted lines
>Am 12.09.25 um 22:16 schrieb rsbecker@nexbridge.com:
>> I am trying to integrate a custom mergetool with a shell wrapper.
>> What I get from the online help is the following description referring
>> to the command and environment variables.
>>
>> mergetool.<tool>.cmd
>> Specify the command to invoke the specified merge tool.
>> The specified command is evaluated in shell with the following
>> variables available: BASE is the name of a
>
>Take note: this talks about "variables", not "environment variables".
>
>> temporary file containing the common base of the files to be merged,
>> if available; LOCAL is the name of a temporary file containing the
>> contents of the file on the current branch; REMOTE is the name of a
>> temporary file containing the contents of the file from the branch
>> being merged; MERGED contains the name of the file to which the merge
>> tool should write the results of a successful merge.
>>
>> When I try to use this from a shell, simply with:
>> #!/bin/sh
>> env
>> exit 1
>>
>> the described environment variables: BASE, LOCAL, REMOTE, and MERGED,
>> are not present.
>
>Look at the scripts in the directory mergetools/ and note that they are only (large)
>shell code fragements without a shbang line. They are not even executable.

Let me try to infer what is happening and please correct me if my assumptions are wrong:

Git includes an existing shell fragment with the appropriate tool name from git-core/mergetools/tool-name instead of creating a dedicated shell in which to run the merge tool script.

It then uses ${merge-tool-path} to execute the tool based on whether diff_cmd() or merge_cmd() is invoked. Because BASE, LOCAL, REMOTE, and MERGED are not exported, they are not visible to sub-shells.

This does not apply if the tool is unknown to the mergetools directory, so must be contributed and packaged into git to work according to the documentation.

So a custom mergetool will not have access to these variables and has to hack through what is in the working index based on file_BASE_num, etc. instead of having direct information on what is being merged.

That about right?
Johannes Sixt· Sep 13, 2025, 21:03 UTC · re: rsbecker@nexbridge.com · lore

Re: [QUESTION] mergetool environment variables

Am 13.09.25 um 16:42 schrieb rsbecker@nexbridge.com:
> Let me try to infer what is happening and please correct me if my assumptions
> are wrong:

I'm sorry to say that I can't help. I tried to disentangle what is going on, but this stuff is far too convoluted to be understood in a few minutes. I cannot tell if it is possible to write a mergetool that is not installed with Git.

I would just copy one of the existing tool scripts and run `make install` from the Git source directory.

-- Hannes
rsbecker@nexbridge.com· Sep 14, 2025, 00:18 UTC · re: Johannes Sixt · lore

RE: [QUESTION] mergetool environment variables

On September 13, 2025 5:04 PM, Johannes Sixt wrote:
Show 13 quoted lines
>To: rsbecker@nexbridge.com
>Cc: git@vger.kernel.org
>Subject: Re: [QUESTION] mergetool environment variables
>
>Am 13.09.25 um 16:42 schrieb rsbecker@nexbridge.com:
>> Let me try to infer what is happening and please correct me if my
>> assumptions are wrong:
>I'm sorry to say that I can't help. I tried to disentangle what is going on, but this
>stuff is far too convoluted to be understood in a few minutes. I cannot tell if it is
>possible to write a mergetool that is not installed with Git.
>
>I would just copy one of the existing tool scripts and run `make install` from the Git
>source directory.

Yes, it needs to be in the git install area. Adding export BASE export LOCAL, etc., works to resolve the situation. I wonder whether that should be documented.

Junio C Hamano· Sep 14, 2025, 06:38 UTC · re: rsbecker@nexbridge.com · lore

Re: [QUESTION] mergetool environment variables

<rsbecker@nexbridge.com> writes:
> Yes, it needs to be in the git install area. Adding export BASE export LOCAL, etc.,
> works to resolve the situation. I wonder whether that should be documented.

I am not a mergetool user, but I do not think that is how the thing was intended to be used in the first place.

The documentation that may talk about variables BASE etc. (not "environment variables") are meant for those who add their new tool to the existing mergetool/difftool infrastructure, which means that their tool's definition must be dot-sourceable just like any of these tools defined in mergetools/ directory. You'd add yours there, mimicking what they do, and add a handful of shell functions to be called. git-mergetool--lib would then use

    . "$MERGE_TOOLS_DIR/${tool%[0-9]}"
inside its setup_tool function to read your definition.
Phillip Wood· Sep 14, 2025, 13:48 UTC · re: rsbecker@nexbridge.com · lore

Re: [QUESTION] mergetool environment variables

Hi Randall
On 14/09/2025 01:18, rsbecker@nexbridge.com wrote:
Show 17 quoted lines
> On September 13, 2025 5:04 PM, Johannes Sixt wrote:
>> To: rsbecker@nexbridge.com
>> Cc: git@vger.kernel.org
>> Subject: Re: [QUESTION] mergetool environment variables
>>
>> Am 13.09.25 um 16:42 schrieb rsbecker@nexbridge.com:
>>> Let me try to infer what is happening and please correct me if my
>>> assumptions are wrong:
>> I'm sorry to say that I can't help. I tried to disentangle what is going on, but this
>> stuff is far too convoluted to be understood in a few minutes. I cannot tell if it is
>> possible to write a mergetool that is not installed with Git.
>>
>> I would just copy one of the existing tool scripts and run `make install` from the Git
>> source directory.
> 
> Yes, it needs to be in the git install area. Adding export BASE export LOCAL, etc.,
> works to resolve the situation. I wonder whether that should be documented.

Looking at t7610-mergetool.sh I think you can use mergetool.<tool>.cmd to call a user defined merge tool. The value of the config variable is eval'd in the shell so if you run

     git config mergetool.my-tool.cmd 'my-tool "$BASE" "$LOCAL" "$REMOTE"'
then
     git mergetool --tool=my-tool
will run
     my-tool <base-file> <local-file> <remote-file>
on each unmerged file
Thanks
Phillip
D. Ben Knoble· Sep 15, 2025, 15:35 UTC · re: Phillip Wood · lore

Re: [QUESTION] mergetool environment variables

The text of this reply sat in my drafts, so my apologies for getting it out later than I intended. I agree with Phillip's reply below, to which I've moved the text so it makes sense :)

On Sun, Sep 14, 2025 at 9:51 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 41 quoted lines
>
> Hi Randall
>
> On 14/09/2025 01:18, rsbecker@nexbridge.com wrote:
> > On September 13, 2025 5:04 PM, Johannes Sixt wrote:
> >> To: rsbecker@nexbridge.com
> >> Cc: git@vger.kernel.org
> >> Subject: Re: [QUESTION] mergetool environment variables
> >>
> >> Am 13.09.25 um 16:42 schrieb rsbecker@nexbridge.com:
> >>> Let me try to infer what is happening and please correct me if my
> >>> assumptions are wrong:
> >> I'm sorry to say that I can't help. I tried to disentangle what is going on, but this
> >> stuff is far too convoluted to be understood in a few minutes. I cannot tell if it is
> >> possible to write a mergetool that is not installed with Git.
> >>
> >> I would just copy one of the existing tool scripts and run `make install` from the Git
> >> source directory.
> >
> > Yes, it needs to be in the git install area. Adding export BASE export LOCAL, etc.,
> > works to resolve the situation. I wonder whether that should be documented.
>
> Looking at t7610-mergetool.sh I think you can use mergetool.<tool>.cmd
> to call a user defined merge tool. The value of the config variable is
> eval'd in the shell so if you run
>
>      git config mergetool.my-tool.cmd 'my-tool "$BASE" "$LOCAL" "$REMOTE"'
>
> then
>
>      git mergetool --tool=my-tool
>
> will run
>
>      my-tool <base-file> <local-file> <remote-file>
>
> on each unmerged file
>
> Thanks
>
> Phillip

I run a custom merge tool, and I am fairly certain it has access to these variables. But I pass them in the config defining the tool to the « main » command in the versions where I use them.

See history around https://github.com/benknoble/Dotfiles/blob/4a4fe9678bdc5b34dc826058fbe85d29cc4d7722/links/gitconfig#L130.

Otherwise this would seem an unfortunate interface.
-- 
D. Ben Knoble

← back to recent threads