@harryisfish/gitt 1.6.6 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,7 +18,8 @@ async function cleanDeletedBranches(options = {}) {
18
18
  const state = {
19
19
  mainBranch: '',
20
20
  currentBranch: '',
21
- deletedBranches: []
21
+ deletedBranches: [],
22
+ isStaleMode: options.stale || false
22
23
  };
23
24
  // Phase 1: Discovery
24
25
  const discoveryTasks = new listr2_1.Listr([
@@ -84,12 +85,19 @@ async function cleanDeletedBranches(options = {}) {
84
85
  }
85
86
  // Filter out worktree branches
86
87
  candidates = candidates.filter(c => !worktreeBranches.includes(c.name));
87
- // Check merge status for each branch
88
- const branchesWithStatus = await Promise.all(candidates.map(async (c) => {
89
- const isMerged = await (0, git_1.isBranchMerged)(c.name, ctx.mainBranch);
90
- return { ...c, isMerged };
91
- }));
92
- ctx.deletedBranches = branchesWithStatus;
88
+ // For stale mode, check merge status; for gone mode, skip (PR completed = safe to delete)
89
+ if (options.stale) {
90
+ const branchesWithStatus = await Promise.all(candidates.map(async (c) => {
91
+ const isMerged = await (0, git_1.isBranchMerged)(c.name, ctx.mainBranch);
92
+ return { ...c, isMerged };
93
+ }));
94
+ // In stale mode, only auto-delete merged branches
95
+ ctx.deletedBranches = branchesWithStatus.filter(b => b.isMerged);
96
+ }
97
+ else {
98
+ // Gone mode: remote deleted = PR completed, safe to delete all
99
+ ctx.deletedBranches = candidates;
100
+ }
93
101
  }
94
102
  }
95
103
  ]);
@@ -102,9 +110,9 @@ async function cleanDeletedBranches(options = {}) {
102
110
  if (options.interactive) {
103
111
  try {
104
112
  const choices = state.deletedBranches.map(b => ({
105
- name: `${b.name} (${b.reason}${b.isMerged ? '' : ', Unmerged'})`,
113
+ name: `${b.name} (${b.reason})`,
106
114
  value: b,
107
- checked: b.isMerged // Only check merged branches by default
115
+ checked: true // All candidates are safe to delete
108
116
  }));
109
117
  const selected = await (0, prompts_1.checkbox)({
110
118
  message: 'Select branches to delete:',
@@ -117,15 +125,7 @@ async function cleanDeletedBranches(options = {}) {
117
125
  throw new errors_1.UserCancelError('Operation cancelled');
118
126
  }
119
127
  }
120
- else {
121
- // Auto mode: Filter out unmerged branches
122
- const unmerged = state.deletedBranches.filter(b => !b.isMerged);
123
- state.deletedBranches = state.deletedBranches.filter(b => b.isMerged);
124
- if (state.deletedBranches.length === 0 && unmerged.length > 0) {
125
- (0, errors_1.printSuccess)(`No merged branches to clean up (${unmerged.length} unmerged branch${unmerged.length > 1 ? 'es' : ''} skipped, use -i to review)`);
126
- return;
127
- }
128
- }
128
+ // Non-interactive mode: delete all candidates (already filtered in discovery phase)
129
129
  if (state.deletedBranches.length === 0) {
130
130
  (0, errors_1.printSuccess)('No branches selected for deletion');
131
131
  return;
package/dist/utils/git.js CHANGED
@@ -79,11 +79,28 @@ async function setMainBranch(branch) {
79
79
  }
80
80
  /**
81
81
  * Check if a branch is merged into the main branch.
82
+ * Supports regular merge, squash merge, and rebase merge detection.
82
83
  */
83
84
  async function isBranchMerged(branch, mainBranch) {
84
85
  try {
86
+ // Method 1: Check regular merge with git branch --merged
85
87
  const mergedBranches = await git.branch(['--merged', mainBranch]);
86
- return mergedBranches.all.includes(branch);
88
+ if (mergedBranches.all.includes(branch)) {
89
+ return true;
90
+ }
91
+ // Method 2: Check squash/rebase merge with git cherry
92
+ // git cherry returns empty or all lines start with '-' if fully merged
93
+ // '-' means the commit exists in upstream (merged)
94
+ // '+' means the commit does not exist in upstream (not merged)
95
+ const cherryOutput = await git.raw(['cherry', mainBranch, branch]);
96
+ const lines = cherryOutput.trim().split('\n').filter(Boolean);
97
+ // If no commits unique to branch, or all commits are merged (start with -)
98
+ if (lines.length === 0) {
99
+ return true;
100
+ }
101
+ // Check if all commits are merged (all lines start with '-')
102
+ const hasUnmergedCommits = lines.some(line => line.startsWith('+'));
103
+ return !hasUnmergedCommits;
87
104
  }
88
105
  catch (error) {
89
106
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harryisfish/gitt",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
4
4
  "description": "A command-line tool to help you manage Git repositories and remote repositories, such as keeping in sync, pushing, pulling, etc.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {