From 626a20ac97a20ea44468f547e332c5b09fd059c7 Mon Sep 17 00:00:00 2001 From: Sina Hinderks Date: Thu, 3 Jul 2025 04:20:44 +0200 Subject: [PATCH] enhance: respect git config `merge.ff` (#1495) This adds another configuration possibility for the default merge mode to the already existing per branch git configuration `branch..mergeoptions` (#540) and the per repo preference "Preferred Merge Mode" (#1156). Defined values: - `false`: do no fast-forward merge - `only`: do only a fast-forward merge This is configurable by for example `git config set --global merge.ff ` for a global (meaning the current user) configuration. The priority between these configurations/preferences is: - git configuration `branch..mergeoptions` (#540) - git configuration `merge.ff` - preference "Preferred Merge Mode" (#1156) --- src/Models/MergeMode.cs | 25 ++++++++++++++++----- src/ViewModels/Merge.cs | 48 ++++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/Models/MergeMode.cs b/src/Models/MergeMode.cs index 5dc70030..fdb26b51 100644 --- a/src/Models/MergeMode.cs +++ b/src/Models/MergeMode.cs @@ -2,13 +2,28 @@ { public class MergeMode { + public static readonly MergeMode Default = + new MergeMode("Default", "Fast-forward if possible", ""); + + public static readonly MergeMode FastForward = + new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only"); + + public static readonly MergeMode NoFastForward = + new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"); + + public static readonly MergeMode Squash = + new MergeMode("Squash", "Squash merge", "--squash"); + + public static readonly MergeMode DontCommit + = new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"); + public static readonly MergeMode[] Supported = [ - new MergeMode("Default", "Fast-forward if possible", ""), - new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only"), - new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"), - new MergeMode("Squash", "Squash merge", "--squash"), - new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"), + Default, + FastForward, + NoFastForward, + Squash, + DontCommit, ]; public string Name { get; set; } diff --git a/src/ViewModels/Merge.cs b/src/ViewModels/Merge.cs index d7b6a29c..7620d9ef 100644 --- a/src/ViewModels/Merge.cs +++ b/src/ViewModels/Merge.cs @@ -34,7 +34,7 @@ namespace SourceGit.ViewModels Source = source; Into = into; - Mode = forceFastForward ? Models.MergeMode.Supported[1] : AutoSelectMergeMode(); + Mode = forceFastForward ? Models.MergeMode.FastForward : AutoSelectMergeMode(); } public Merge(Repository repo, Models.Commit source, string into) @@ -82,27 +82,49 @@ namespace SourceGit.ViewModels } private Models.MergeMode AutoSelectMergeMode() + { + return + GetGitConfigBranchMergeOptions() + ?? GetGitConfigMergeFF() + ?? GetSettingsPreferredMergeMode(); + } + + private Models.MergeMode GetSettingsPreferredMergeMode() { var preferredMergeModeIdx = _repo.Settings.PreferredMergeMode; if (preferredMergeModeIdx < 0 || preferredMergeModeIdx > Models.MergeMode.Supported.Length) preferredMergeModeIdx = 0; var defaultMergeMode = Models.MergeMode.Supported[preferredMergeModeIdx]; - var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions"); - if (string.IsNullOrEmpty(config)) - return defaultMergeMode; - if (config.Equals("--ff-only", StringComparison.Ordinal)) - return Models.MergeMode.Supported[1]; - if (config.Equals("--no-ff", StringComparison.Ordinal)) - return Models.MergeMode.Supported[2]; - if (config.Equals("--squash", StringComparison.Ordinal)) - return Models.MergeMode.Supported[3]; - if (config.Equals("--no-commit", StringComparison.Ordinal) || config.Equals("--no-ff --no-commit", StringComparison.Ordinal)) - return Models.MergeMode.Supported[4]; - return defaultMergeMode; } + private Models.MergeMode GetGitConfigMergeFF() + { + var config = new Commands.Config(_repo.FullPath).Get("merge.ff"); + return config switch + { + null or "" => null, + "false" => Models.MergeMode.NoFastForward, + "only" => Models.MergeMode.FastForward, + _ => null + }; + } + + private Models.MergeMode GetGitConfigBranchMergeOptions() + { + var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions"); + return config switch + { + null or "" => null, + "--ff-only" => Models.MergeMode.FastForward, + "--no-ff" => Models.MergeMode.NoFastForward, + "--squash" => Models.MergeMode.Squash, + "--no-commit" or "--no-ff --no-commit" => Models.MergeMode.DontCommit, + _ => null + }; + } + private readonly Repository _repo = null; private readonly string _sourceName; }