fix(worktrees): detect external merges, clean up empty dirs, prune in owning repo

- ContentInMain: HEAD ancestor of the default branch or squash-merged
  (merge-tree == target tree), against local origin/<default> without fetch;
  list_worktrees mergedIntoMain and the overview modal ("merged (external)")
  use it, "Cleanup finished" takes clean Active rows that are in main
- cleanup_task_worktree skips the dirty check for a non-git directory
- prune / worktree remove / branch -D run in the repo owning the worktree
  (git-common-dir), not the list's working dir; branch already gone reports
  branchDeleted=true
This commit is contained in:
mika kuns
2026-10-02 09:07:43 +02:00
parent 9c015f34cc
commit 0c0bb7f24c
12 changed files with 333 additions and 22 deletions
+7
View File
@@ -489,6 +489,13 @@ public sealed class GitService
return head.StartsWith("origin/", StringComparison.Ordinal) ? head["origin/".Length..] : head;
}
/// <summary>Absolute path of the <c>.git</c> dir shared by all worktrees of the repo owning <paramref name="dir"/>, or null.</summary>
public async Task<string?> GetCommonDirAsync(string dir, CancellationToken ct = default)
{
var (exitCode, stdout, _) = await RunGitAsync(dir, ["rev-parse", "--path-format=absolute", "--git-common-dir"], ct);
return exitCode == 0 && !string.IsNullOrWhiteSpace(stdout) ? stdout.Trim() : null;
}
/// <summary><c>git merge --ff-only</c>: moves the checked-out branch to <paramref name="sourceRef"/> or fails without touching it.</summary>
public async Task<(int ExitCode, string Stderr)> MergeFastForwardOnlyAsync(
string worktreePath, string sourceRef, CancellationToken ct = default)