feature: merge multiple heads (#793)

* feature: allow merging multiple heads
* feature: allow merging multiple branches from branch tree
This commit is contained in:
Dmitrij D. Czarkoff 2024-12-09 13:04:25 +00:00 committed by GitHub
parent c9c7fb5d5b
commit dce33fdf60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 232 additions and 10 deletions

View file

@ -228,22 +228,28 @@ namespace SourceGit.ViewModels
{
var selected = new List<Models.Commit>();
var canCherryPick = true;
var canMerge = true;
foreach (var item in list.SelectedItems)
{
if (item is Models.Commit c)
{
selected.Add(c);
if (c.IsMerged || c.Parents.Count > 1)
if (c.IsMerged)
{
canMerge = false;
canCherryPick = false;
}
else if (c.Parents.Count > 1)
{
canCherryPick = false;
}
}
}
// Sort selected commits in order.
selected.Sort((l, r) =>
{
return _commits.IndexOf(r) - _commits.IndexOf(l);
});
selected.Sort((l, r) => _commits.IndexOf(r) - _commits.IndexOf(l));
var multipleMenu = new ContextMenu();
@ -259,9 +265,25 @@ namespace SourceGit.ViewModels
e.Handled = true;
};
multipleMenu.Items.Add(cherryPickMultiple);
multipleMenu.Items.Add(new MenuItem() { Header = "-" });
}
if (canMerge)
{
var mergeMultiple = new MenuItem();
mergeMultiple.Header = App.Text("CommitCM.MergeMultiple");
mergeMultiple.Icon = App.CreateMenuIcon("Icons.Merge");
mergeMultiple.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new MergeMultiple(_repo, selected));
e.Handled = true;
};
multipleMenu.Items.Add(mergeMultiple);
}
if (canCherryPick || canMerge)
multipleMenu.Items.Add(new MenuItem() { Header = "-" });
var saveToPatchMultiple = new MenuItem();
saveToPatchMultiple.Icon = App.CreateMenuIcon("Icons.Diff");
saveToPatchMultiple.Header = App.Text("CommitCM.SaveAsPatch");

View file

@ -37,7 +37,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
var succ = new Commands.Merge(_repo.FullPath, Source, SelectedMode.Arg, SetProgressDescription).Exec();
var succ = new Commands.Merge(_repo.FullPath, Source, SelectedMode.Arg, null, SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using SourceGit.Models;
namespace SourceGit.ViewModels
{
public class MergeMultiple : Popup
{
public List<string> Strategies = ["octopus", "ours"];
public List<Commit> Targets
{
get;
private set;
}
public bool AutoCommit
{
get;
set;
}
public MergeStrategy Strategy
{
get;
set;
}
public MergeMultiple(Repository repo, List<Commit> targets)
{
_repo = repo;
Targets = targets;
AutoCommit = true;
Strategy = MergeStrategy.ForMultiple.Find(s => s.Arg == null);
View = new Views.MergeMultiple() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Merge head(s) ...";
return Task.Run(() =>
{
var succ = new Commands.Merge(
_repo.FullPath,
string.Join(" ", Targets.ConvertAll(c => c.Decorators.Find(d => d.Type == DecoratorType.RemoteBranchHead || d.Type == DecoratorType.LocalBranchHead)?.Name ?? c.Decorators.Find(d => d.Type == DecoratorType.Tag)?.Name ?? c.SHA)),
AutoCommit ? string.Empty : "--no-commit",
Strategy?.Arg,
SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private readonly Repository _repo = null;
}
}

View file

@ -172,7 +172,7 @@ namespace SourceGit.ViewModels
else
{
SetProgressDescription($"Merge {_selectedBranch.FriendlyName} into {_current.Name} ...");
rs = new Commands.Merge(_repo.FullPath, _selectedBranch.FriendlyName, "", SetProgressDescription).Exec();
rs = new Commands.Merge(_repo.FullPath, _selectedBranch.FriendlyName, "", null, SetProgressDescription).Exec();
}
}
else

View file

@ -13,6 +13,7 @@ using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using SourceGit.Models;
namespace SourceGit.ViewModels
{
@ -950,6 +951,12 @@ namespace SourceGit.ViewModels
PopupHost.ShowPopup(new DeleteMultipleBranches(this, branches, isLocal));
}
public void MergeMultipleBranches(List<Models.Branch> branches)
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new MergeMultiple(this, branches.ConvertAll(b => _histories?.Commits?.Find(c => c.SHA == b.Head))));
}
public void CreateNewTag()
{
if (_currentBranch == null)