janou195
janou195

Reputation: 1205

How to have meld as git mergetool to only show conflict and not differences?

When I use meld as git mergetool for solving conflict while merging, meld shows me the differences between local/output and remote/output files (in blue or green) that git automatically solves, and not only the actual conflicts (that are red highlighted). And when I click on the down arrow, it goes to the next (blue/green) difference, and not to the next conflict (red). In this topic, a picture illustrates this.

How could I

Upvotes: 16

Views: 7381

Answers (4)

VonC
VonC

Reputation: 1323045

In addition to meld-specific parameters, you now have new Git options:

With Git 2.31 (Q1 2021), "git mergetool"(man) feeds three versions (base, local, and remote) of a conflicted path unmodified.
The command learned optionally to prepare these files with unconflicted parts already resolved. OP could enable this behaviour for their meld mergetool with:

git config --global mergetool.meld.hideResolved true

See commit 9d9cf23, commit de8dafb, commit 98ea309 (09 Feb 2021) by Seth House (whiteinge).
(Merged by Junio C Hamano -- gitster -- in commit 78a26cb, 17 Feb 2021)

mergetool: add hideResolved configuration

Original-implementation-by: Felipe Contreras
Signed-off-by: Seth House

The purpose of a mergetool is to help the user resolve any conflicts that Git cannot automatically resolve.
If there is a conflict that must be resolved manually Git will write a file named MERGED which contains everything Git was able to resolve by itself and also everything that it was not able to resolve wrapped in conflict markers.

One way to think of MERGED is as a two- or three-way diff.
If each "side" of the conflict markers is separately extracted an external tool can represent those conflicts as a side-by-side diff.

However many mergetools instead diff LOCAL and REMOTE both of which contain versions of the file from before the merge.
Since the conflicts Git resolved automatically are not present it forces the user to manually re-resolve those conflicts.
Some mergetools also show MERGED but often only for reference and not as the focal point to resolve the conflicts.

This adds a mergetool.hideResolved flag that will overwrite LOCAL and REMOTE with each corresponding "side" of a conflicted file and thus hide all conflicts that Git was able to resolve itself.
Overwriting these files will immediately benefit any mergetool that uses them without requiring any changes to the tool.

No adverse effects were noted in a small survey of popular mergetools so this behavior defaults to true.
However it can be globally disabled by setting mergetool.hideResolved to false.

See "Mergetools: Stop doing three-way merges!"

git config now includes in its man page:

mergetool.hideResolved

During a merge Git will automatically resolve as many conflicts as possible and write the 'MERGED' file containing conflict markers around any conflicts that it cannot resolve; 'LOCAL' and 'REMOTE' normally represent the versions of the file from before Git's conflict resolution.

This flag causes 'LOCAL' and 'REMOTE' to be overwriten so that only the unresolved conflicts are presented to the merge tool.

Can be configured per-tool via the mergetool.<tool>.hideResolved configuration variable. Defaults to true.

In the OP's case:

git config --global mergetool.meld.hideResolved true

This is described in:

mergetool: add per-tool support and overrides for the hideResolved flag

Helped-by: Johannes Sixt
Helped-by: Junio C Hamano
Signed-off-by: Seth House

Add a per-tool override flag so that users may enable the flag for one tool and disable it for another by setting mergetool.<tool>.hideResolved to false.

In addition, the author or maintainer of a mergetool may optionally override the default hideResolved value for that mergetool.
If the mergetools/<tool> shell script contains a hide_resolved_enabled function it will be called when the mergetool is invoked and the return value will be used as the default for the hideResolved flag.

hide_resolved_enabled () {
    return 1
}

Disabling may be desirable if the mergetool wants or needs access to the original, unmodified 'LOCAL' and 'REMOTE' versions of the conflicted file.

For example:

  • A tool may use a custom conflict resolution algorithm and prefer to ignore the results of Git's conflict resolution.
  • A tool may want to visually compare/constrast the version of the file from before the merge (saved to 'LOCAL', 'REMOTE', and 'BASE') with Git's conflict resolution results (saved to 'MERGED').

git config now includes in its man page:

mergetool.<tool>.hideResolved

Allows the user to override the global mergetool.hideResolved value for a specific tool.


Note that mergetool.hideResolved actually default to false:

With Git 2.31 (Q1 2021), rc2, disable the recent mergetool's hideresolved feature by default for backward compatibility and safety.

See commit 5320406, commit b2a51c1 (13 Mar 2021) by Jonathan Nieder (artagnon).
(Merged by Junio C Hamano -- gitster -- in commit 8775279, 14 Mar 2021)

mergetool: do not enable hideResolved by default

Reported-by: Dana Dahlstrom
Helped-by: Seth House
Signed-off-by: Jonathan Nieder

When 98ea309 ("mergetool: add hideResolved configuration", 2021-02-09, Git v2.31.0-rc0 -- merge listed in batch #9) introduced the mergetool.hideResolved setting to reduce the clutter in viewing non-conflicted sections of files in a mergetool, it enabled it by default, explaining:

No adverse effects were noted in a small survey of popular mergetools.   
so this behavior defaults to `true`.

In practice, alas, adverse effects do appear.
A few issues:

  1. No indication is shown in the UI that the base, local, and remote versions shown have been modified by additional resolution. This is inherent in the design: the idea of mergetool.hideResolved is to convince a mergetool that expects pristine local, base, and remote files to show partially resolved verisons of those files instead; there is no additional source of information accessible to the mergetool to see where the resolution has happened.

    (By contrast, a mergetool generating the partial resolution from conflict markers for itself would be able to hilight the resolved sections with a different color.)

    A user accustomed to seeing the files without partial resolution gets no indication that this behavior has changed when they upgrade Git.

  2. If the computed merge did not line up the files correctly (for example due to repeated sections in the file), the partially resolved files can be misleading and do not have enough information to reconstruct what happened and compute the correct merge result.

  3. Resolving a conflict can involve information beyond the textual conflict.
    For example, if the local and remote versions added overlapping functionality in different ways, seeing the full unresolved versions of each alongside the base gives information about each side's intent that makes it possible to come up with a resolution that combines those two intents.
    By contrast, when starting with partially resolved versions of those files, one can produce a subtly wrong resolution that includes redundant extra code added by one side that is not needed in the approach taken on the other.

All that said, a user wanting to focus on textual conflicts with reduced clutter can still benefit from mergetool.hideResolved=true as a way to deemphasize sections of the code that resolve cleanly without requiring any changes to the invoked mergetool.
The caveats described above are reduced when the user has explicitly turned this on, because then the user is aware of them.

Flip the default to 'false'.

git config now includes in its man page:

configuration variable. Defaults to false.


Note: With Git 2.48 (Q1 2025), batch 15, end-user experience of "git mergetool"(man) when the command errors out has been improved.

See commit dbaece3, commit acca46d, commit bba503d, commit 0053676, commit fe99a52 (22 Nov 2024) by Philippe Blain (phil-blain).
(Merged by Junio C Hamano -- gitster -- in commit 9cd1e2e, 10 Dec 2024)

git-mergetool--lib.sh: add error message if 'setup_user_tool' fails

Signed-off-by: Philippe Blain

In git-mergetool--lib.sh::setup_tool, we check if the given tool is a known builtin tool, a known variant, or a user-defined tool by calling setup_user_tool, and we return with the exit code from setup_user_tool if it was called.
setup_user_tool checks if {diff,merge}tool.$tool.cmd is set and quietly returns with an error if not.

This leads to the following invocation quietly failing:

git mergetool --tool=unknown

which is not very user-friendly.
Adjust setup_tool to output an error message before returning if setup_user_tool returned with an error.

Note that we do not check the result of the second call to setup_user_tool in setup_tool, as this call is only meant to allow users to redefine 'cmd' for a builtin tool; it is not an error if they have not done so.

Note that this behaviour of quietly failing is a regression dating back to de8dafb ("mergetool: break setup_tool out into separate initialization function", 2021-02-09, Git v2.31.0-rc0 -- merge listed in batch #9), as before this commit an unknown mergetool would be diagnosed in get_merge_tool_path when called from run_merge_tool.

We now have the error message:

error: ${TOOL_MODE}tool.$tool.cmd not set for tool '$tool'

And:

error: unknown tool variant '$tool'

Upvotes: 9

matiasdim
matiasdim

Reputation: 527

If you use cmd+D in your mac it will got to the next conflict, no matter how many changes it is showing. Or in the menu go to Find -> Go Next -> Conflict

Upvotes: 0

Joseph Thomson
Joseph Thomson

Reputation: 10393

Add the following to your .gitconfig:

[mergetool "meld"]
  cmd = meld --auto-merge "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"

This is the same command Git runs by default with --auto-merge specified so that Meld automatically resolves what it can.

Upvotes: 11

chrisdembia
chrisdembia

Reputation: 733

In meld, you can click Changes > Merge All, which will merge most changes except for the conflicts.

Upvotes: 7

Related Questions