feature: supports to overwrite existing branch while creating new branch (#1349)

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-05-23 11:27:45 +08:00
parent 594ffc0d1a
commit 76a197aae7
No known key found for this signature in database
9 changed files with 74 additions and 36 deletions

View file

@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Text;
namespace SourceGit.Commands
{
public static class Branch
{
@ -11,12 +13,20 @@
return cmd.ReadToEnd().StdOut.Trim();
}
public static bool Create(string repo, string name, string basedOn, Models.ICommandLog log)
public static bool Create(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("branch ");
if (force)
builder.Append("-f ");
builder.Append(name);
builder.Append(" ");
builder.Append(basedOn);
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch {name} {basedOn}";
cmd.Args = builder.ToString();
cmd.Log = log;
return cmd.Exec();
}
@ -31,16 +41,6 @@
return cmd.Exec();
}
public static bool ResetWithoutCheckout(string repo, string name, string to, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -f {name} {to}";
cmd.Log = log;
return cmd.Exec();
}
public static bool SetUpstream(string repo, string name, string upstream, Models.ICommandLog log)
{
var cmd = new Command();

View file

@ -13,15 +13,28 @@ namespace SourceGit.Commands
public bool Branch(string branch, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --progress {branch}";
var builder = new StringBuilder();
builder.Append("checkout --progress ");
if (force)
builder.Append("--force ");
builder.Append(branch);
Args = builder.ToString();
return Exec();
}
public bool Branch(string branch, string basedOn, bool force)
public bool Branch(string branch, string basedOn, bool force, bool allowOverwrite)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout --progress -b {branch} {basedOn}";
var builder = new StringBuilder();
builder.Append("checkout --progress ");
builder.Append(allowOverwrite ? "-B " : "-b ");
if (force)
builder.Append("--force ");
builder.Append(branch);
builder.Append(" ");
builder.Append(basedOn);
Args = builder.ToString();
return Exec();
}

View file

@ -217,6 +217,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter branch name.</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Spaces will be replaced with dashes.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Create Local Branch</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Overwrite existing branch</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Create Tag...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">New Tag At:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">GPG signing</x:String>

View file

@ -221,6 +221,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填写分支名称。</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格将被替换为'-'符号</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">创建本地分支</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允许重置已存在的分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新建标签 ...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">标签位于 </x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG签名</x:String>

View file

@ -221,6 +221,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">輸入分支名稱。</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格將以英文破折號取代</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">建立本機分支</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允許覆寫現有分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新增標籤...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">標籤位於:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用 GPG 簽章</x:String>

View file

@ -43,6 +43,16 @@ namespace SourceGit.ViewModels
get => _repo.IsBare;
}
public bool AllowOverwrite
{
get => _allowOverwrite;
set
{
if (SetProperty(ref _allowOverwrite, value))
ValidateProperty(_name, nameof(Name));
}
}
public bool IsRecurseSubmoduleVisible
{
get => _repo.Submodules.Count > 0;
@ -88,18 +98,24 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
{
var creator = ctx.ObjectInstance as CreateBranch;
if (creator == null)
return new ValidationResult("Missing runtime context to create branch!");
var fixedName = creator.FixName(name);
foreach (var b in creator._repo.Branches)
if (ctx.ObjectInstance is CreateBranch creator)
{
if (b.FriendlyName == fixedName)
return new ValidationResult("A branch with same name already exists!");
}
if (!creator._allowOverwrite)
{
var fixedName = creator.FixName(name);
foreach (var b in creator._repo.Branches)
{
if (b.FriendlyName == fixedName)
return new ValidationResult("A branch with same name already exists!");
}
}
return ValidationResult.Success;
return ValidationResult.Success;
}
else
{
return new ValidationResult("Missing runtime context to create branch!");
}
}
public override Task<bool> Sure()
@ -119,7 +135,7 @@ namespace SourceGit.ViewModels
var needPopStash = false;
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true, _allowOverwrite);
}
else
{
@ -137,7 +153,7 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false, _allowOverwrite);
}
if (succ)
@ -155,7 +171,7 @@ namespace SourceGit.ViewModels
}
else
{
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, log);
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
}
log.Complete();
@ -201,5 +217,6 @@ namespace SourceGit.ViewModels
private readonly Repository _repo = null;
private string _name = null;
private readonly string _baseOnRevision = null;
private bool _allowOverwrite = false;
}
}

View file

@ -116,7 +116,7 @@ namespace SourceGit.ViewModels
var masterBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_master, StringComparison.Ordinal));
if (masterBranch == null)
{
succ = Commands.Branch.Create(_repo.FullPath, _master, current.Head, log);
succ = Commands.Branch.Create(_repo.FullPath, _master, current.Head, true, log);
if (!succ)
{
log.Complete();
@ -128,7 +128,7 @@ namespace SourceGit.ViewModels
var developBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_develop, StringComparison.Ordinal));
if (developBranch == null)
{
succ = Commands.Branch.Create(_repo.FullPath, _develop, current.Head, log);
succ = Commands.Branch.Create(_repo.FullPath, _develop, current.Head, true, log);
if (!succ)
{
log.Complete();

View file

@ -40,7 +40,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
var succ = Commands.Branch.ResetWithoutCheckout(_repo.FullPath, Target.Name, _revision, log);
var succ = Commands.Branch.Create(_repo.FullPath, Target.Name, _revision, true, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;

View file

@ -14,7 +14,7 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.CreateBranch.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto,Auto" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,32,Auto,Auto,Auto" ColumnDefinitions="140,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -80,11 +80,16 @@
</Border>
<CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.OverwriteExisting}"
IsChecked="{Binding AllowOverwrite, Mode=TwoWay}"
ToolTip.Tip="checkout -B or branch -f"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
<CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
ToolTip.Tip="--recurse-submodules">