From 1c7d8553ea2e0abc961b8639ce0ca0650d8781eb Mon Sep 17 00:00:00 2001 From: heartacker Date: Sun, 17 May 2026 16:59:06 +0800 Subject: [PATCH 1/2] fix: use CoreEditor instead of RebaseEditor when rebase --continue (fix #2352) - Use `CoreEditor` in rebase continue to prevent re-triggering the sequence editor on each `--continue` action - Avoids git mis-counting done/todo entries and writing duplicate commit entries to the done file mid-rebase (cherry picked from commit c14b2cedf850ab64d38cea44decf7abe871893fb) --- src/ViewModels/InProgressContexts.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ViewModels/InProgressContexts.cs b/src/ViewModels/InProgressContexts.cs index 5854bb6c3..d924bff59 100644 --- a/src/ViewModels/InProgressContexts.cs +++ b/src/ViewModels/InProgressContexts.cs @@ -114,7 +114,11 @@ public RebaseInProgress(Repository repo) { WorkingDirectory = repo.FullPath, Context = repo.FullPath, - Editor = Commands.Command.EditorType.RebaseEditor, + // Use CoreEditor instead of RebaseEditor to avoid re-triggering + // the sequence.editor on each --continue. Re-triggering the todo + // editor mid-rebase can cause git to mis-count done/todo entries + // and write duplicate commit entries to the done file. + Editor = Commands.Command.EditorType.CoreEditor, Args = "rebase --continue", }; From 3a61db01b9ca69e140f28c9567261e9870016b9f Mon Sep 17 00:00:00 2001 From: heartacker Date: Sun, 17 May 2026 15:29:21 +0800 Subject: [PATCH 2/2] fix: use cached SelfExecPath to avoid '(deleted)' editor issue eg : dotnet build with hot-reload "~/data/home/gits/sourcegit/src/bin/Debug/net10.0/SourceGit (deleted)" --rebase-todo-editor: 1: ~/gits/sourcegit/src/bin/Debug/net10.0/SourceGit (deleted): not found error: There was a problem with the editor '"~/gits/sourcegit/src/bin/Debug/net10.0/SourceGit (deleted)" --rebase-todo-editor'. --- src/Commands/Command.cs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 2c453b9a1..2163bf9b2 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -10,6 +11,24 @@ namespace SourceGit.Commands { public partial class Command { + /// + /// Cached path to the current process executable. + /// Uses Environment.ProcessPath (instead of MainModule.FileName) to avoid + /// the "(deleted)" suffix issue when the binary is overwritten during + /// development (e.g., dotnet build with hot-reload). + /// + internal static readonly string SelfExecPath = ResolveSelfExecPath(); + + private static string ResolveSelfExecPath() + { + var path = Environment.ProcessPath; + if (!string.IsNullOrEmpty(path) && File.Exists(path)) + return path; + + // fallback to old method + return Process.GetCurrentProcess().MainModule!.FileName; + } + public class Result { public bool IsSuccess { get; set; } = false; @@ -172,8 +191,10 @@ protected ProcessStartInfo CreateGitStartInfo(bool redirect) } // Force using this app as SSH askpass program - var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName; - start.Environment.Add("SSH_ASKPASS", selfExecFile); // Can not use parameter here, because it invoked by SSH with `exec` + // Uses cached SelfExecPath (resolved once at startup via Environment.ProcessPath) + // instead of Process.GetCurrentProcess().MainModule.FileName to avoid + // the "(deleted)" suffix when the binary is overwritten during development. + start.Environment.Add("SSH_ASKPASS", SelfExecPath); // Can not use parameter here, because it invoked by SSH with `exec` start.Environment.Add("SSH_ASKPASS_REQUIRE", "prefer"); start.Environment.Add("SOURCEGIT_LAUNCH_AS_ASKPASS", "TRUE"); if (!OperatingSystem.IsLinux()) @@ -199,10 +220,10 @@ protected ProcessStartInfo CreateGitStartInfo(bool redirect) switch (Editor) { case EditorType.CoreEditor: - builder.Append($"""-c core.editor="\"{selfExecFile}\" --core-editor" """); + builder.Append($"""-c core.editor="\"{SelfExecPath}\" --core-editor" """); break; case EditorType.RebaseEditor: - builder.Append($"""-c core.editor="\"{selfExecFile}\" --rebase-message-editor" -c sequence.editor="\"{selfExecFile}\" --rebase-todo-editor" -c rebase.abbreviateCommands=true """); + builder.Append($"""-c core.editor="\"{SelfExecPath}\" --rebase-message-editor" -c sequence.editor="\"{SelfExecPath}\" --rebase-todo-editor" -c rebase.abbreviateCommands=true """); break; default: builder.Append("-c core.editor=true ");