diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 2fcf9c646..dc0b85600 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -471,6 +471,19 @@ public void FastForwardNonFastForwardableMergeThrows() } } + [Fact] + public void CanForceFastForwardMergeThroughConfig() + { + string path = CloneMergeTestRepo(); + using (var repo = new Repository(path)) + { + repo.Config.Set("merge.ff", "only"); + + Commit commitToMerge = repo.Branches["normal_merge"].Tip; + Assert.Throws(() => repo.Merge(commitToMerge, Constants.Signature, new MergeOptions())); + } + } + [Fact] public void CanMergeAndNotCommit() { @@ -508,6 +521,24 @@ public void CanForceNonFastForwardMerge() } } + [Fact] + public void CanForceNonFastForwardMergeThroughConfig() + { + string path = CloneMergeTestRepo(); + using (var repo = new Repository(path)) + { + repo.Config.Set("merge.ff", "false"); + + Commit commitToMerge = repo.Branches["fast_forward"].Tip; + + MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions()); + + Assert.Equal(MergeStatus.NonFastForward, result.Status); + Assert.Equal("f58f780d5a0ae392efd4a924450b1bbdc0577d32", result.Commit.Id.Sha); + Assert.False(repo.Index.RetrieveStatus().Any()); + } + } + [Fact] public void VerifyUpToDateMerge() { diff --git a/LibGit2Sharp/MergeOptions.cs b/LibGit2Sharp/MergeOptions.cs index be25665ee..881ffb8f5 100644 --- a/LibGit2Sharp/MergeOptions.cs +++ b/LibGit2Sharp/MergeOptions.cs @@ -12,7 +12,7 @@ public sealed class MergeOptions : IConvertableToGitCheckoutOpts /// Initializes a new instance of the class. /// /// Default behavior: - /// A fast-forward merge will be performed if possible. + /// A fast-forward merge will be performed if possible, unless the merge.ff configuration option is set. /// A merge commit will be committed, if one was created. /// Merge will attempt to find renames. /// @@ -110,9 +110,9 @@ CheckoutStrategy IConvertableToGitCheckoutOpts.CheckoutStrategy public enum FastForwardStrategy { /// - /// Default fast-forward strategy. This will perform a fast-forward merge - /// if possible, otherwise will perform a non-fast-forward merge that - /// results in a merge commit. + /// Default fast-forward strategy. If the merge.ff configuration option is set, + /// it will be used. If it is not set, this will perform a fast-forward merge if + /// possible, otherwise a non-fast-forward merge that results in a merge commit. /// Default = 0, diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index b1ebf6146..a0b5df92c 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -1196,6 +1196,21 @@ public CherryPickResult CherryPick(Commit commit, Signature committer, CherryPic return result; } + private FastForwardStrategy FastForwardStrategyFromMergePreference(GitMergePreference preference) + { + switch (preference) + { + case GitMergePreference.GIT_MERGE_PREFERENCE_NONE: + return FastForwardStrategy.Default; + case GitMergePreference.GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY: + return FastForwardStrategy.FastForwardOnly; + case GitMergePreference.GIT_MERGE_PREFERENCE_NO_FASTFORWARD: + return FastForwardStrategy.NoFastFoward; + default: + throw new InvalidOperationException(String.Format("Unknown merge preference: {0}", preference)); + } + } + /// /// Internal implementation of merge. /// @@ -1217,7 +1232,10 @@ private MergeResult Merge(GitMergeHeadHandle[] mergeHeads, Signature merger, Mer return new MergeResult(MergeStatus.UpToDate); } - switch(options.FastForwardStrategy) + FastForwardStrategy fastForwardStrategy = (options.FastForwardStrategy != FastForwardStrategy.Default) ? + options.FastForwardStrategy : FastForwardStrategyFromMergePreference(mergePreference); + + switch(fastForwardStrategy) { case FastForwardStrategy.Default: if (mergeAnalysis.HasFlag(GitMergeAnalysis.GIT_MERGE_ANALYSIS_FASTFORWARD))