@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.
- package/dist/commands/clean.js +18 -18
- package/dist/utils/git.js +18 -1
- package/package.json +1 -1
package/dist/commands/clean.js
CHANGED
|
@@ -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
|
-
//
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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}
|
|
113
|
+
name: `${b.name} (${b.reason})`,
|
|
106
114
|
value: b,
|
|
107
|
-
checked:
|
|
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
|
-
|
|
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
|
-
|
|
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