Improve Checking out older commits

This commit is contained in:
Canon
2026-02-10 18:11:14 +08:00
parent 4af07f329f
commit 2d7e0c66c5
3 changed files with 63 additions and 15 deletions
+10
View File
@@ -174,6 +174,16 @@ public partial class GitService : IGitService
return true; return true;
} }
public async Task<bool> ResetToCommitAsync(string path, string commitHash, CancellationToken ct = default)
{
var (exitCode, _, _) = await RunGitCommandAsync(path, $"reset --hard \"{commitHash}\"", ct);
if (exitCode != 0)
return false;
await RunGitCommandAsync(path, "submodule update --init --recursive", ct);
return true;
}
public async Task<bool> HasLocalChangesAsync(string path, CancellationToken ct = default) public async Task<bool> HasLocalChangesAsync(string path, CancellationToken ct = default)
{ {
var (exitCode, output, _) = await RunGitCommandAsync(path, "status --porcelain", ct); var (exitCode, output, _) = await RunGitCommandAsync(path, "status --porcelain", ct);
+1
View File
@@ -15,6 +15,7 @@ public interface IGitService
Task<bool> CloneAsync(string url, string targetPath, IProgress<string>? progress = null, IProgress<double>? percentProgress = null, CancellationToken ct = default); Task<bool> CloneAsync(string url, string targetPath, IProgress<string>? progress = null, IProgress<double>? percentProgress = null, CancellationToken ct = default);
Task<IReadOnlyList<string>> GetRemoteBranchesAsync(string path, CancellationToken ct = default); Task<IReadOnlyList<string>> GetRemoteBranchesAsync(string path, CancellationToken ct = default);
Task<bool> CheckoutAsync(string path, string branchOrCommit, CancellationToken ct = default); Task<bool> CheckoutAsync(string path, string branchOrCommit, CancellationToken ct = default);
Task<bool> ResetToCommitAsync(string path, string commitHash, CancellationToken ct = default);
Task<bool> HasLocalChangesAsync(string path, CancellationToken ct = default); Task<bool> HasLocalChangesAsync(string path, CancellationToken ct = default);
Task<IReadOnlyList<GitCommitInfo>> GetCommitHistoryAsync(string path, int limit = 20, CancellationToken ct = default); Task<IReadOnlyList<GitCommitInfo>> GetCommitHistoryAsync(string path, int limit = 20, CancellationToken ct = default);
} }
+42 -5
View File
@@ -467,6 +467,42 @@ public class InteractiveMenu
return; return;
} }
var method = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("How would you like to select a commit?")
.AddChoices(
"Pick from history",
"Enter commit hash manually"
));
if (method == "Enter commit hash manually")
{
var manualHash = AnsiConsole.Ask<string>("Enter commit hash:").Trim();
if (string.IsNullOrEmpty(manualHash))
{
AnsiConsole.MarkupLine("[yellow]No commit hash provided.[/]");
WaitForKey();
return;
}
var label = manualHash.Length > 7 ? manualHash[..7] : manualHash;
var success = await ProgressReporter.WithStatusAsync(
$"Checking out {label}...",
async () => await _gitService.CheckoutAsync(mod.Path, manualHash, ct));
if (success)
{
AnsiConsole.MarkupLine($"[green]Checked out commit {label}[/]");
AnsiConsole.MarkupLine("[yellow]Note: You are now in 'detached HEAD' state.[/]");
}
else
{
AnsiConsole.MarkupLine($"[red]Failed to checkout commit {label}[/]");
}
}
else
{
GitCommitInfo commit = AnsiConsole.Prompt( GitCommitInfo commit = AnsiConsole.Prompt(
new SelectionPrompt<GitCommitInfo>() new SelectionPrompt<GitCommitInfo>()
.Title("Select commit:") .Title("Select commit:")
@@ -475,18 +511,19 @@ public class InteractiveMenu
$"[yellow]{c.ShortHash}[/] [grey]{c.Date.ToLocalTime():yyyy-MM-dd}[/] {Markup.Escape(Truncate(c.Message, 50))}") $"[yellow]{c.ShortHash}[/] [grey]{c.Date.ToLocalTime():yyyy-MM-dd}[/] {Markup.Escape(Truncate(c.Message, 50))}")
.AddChoices(commits)); .AddChoices(commits));
var currentBranch = mod.Branch ?? "HEAD";
var success = await ProgressReporter.WithStatusAsync( var success = await ProgressReporter.WithStatusAsync(
$"Checking out {commit.ShortHash}...", $"Resetting {currentBranch} to {commit.ShortHash}...",
async () => await _gitService.CheckoutAsync(mod.Path, commit.Hash, ct)); async () => await _gitService.ResetToCommitAsync(mod.Path, commit.Hash, ct));
if (success) if (success)
{ {
AnsiConsole.MarkupLine($"[green]Checked out commit {commit.ShortHash}[/]"); AnsiConsole.MarkupLine($"[green]Reset branch '{currentBranch}' to commit {commit.ShortHash}[/]");
AnsiConsole.MarkupLine("[yellow]Note: You are now in 'detached HEAD' state.[/]");
} }
else else
{ {
AnsiConsole.MarkupLine($"[red]Failed to checkout commit {commit.ShortHash}[/]"); AnsiConsole.MarkupLine($"[red]Failed to reset to commit {commit.ShortHash}[/]");
}
} }
WaitForKey(); WaitForKey();