Skip to content

Commit 511cc8b

Browse files
committed
Add AI-powered explanation for unpushed branch changes.
(#4443, #4522)
1 parent 6091397 commit 511cc8b

File tree

5 files changed

+71
-12
lines changed

5 files changed

+71
-12
lines changed

contributions.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
}
2525
},
2626
"gitlens.ai.aiRebaseBranch:graph": {
27-
"label": "AI Recompose branch commits (Preview)...",
27+
"label": "AI Recompose Branch Commits (Preview)",
2828
"icon": "$(sparkle)",
2929
"menus": {
3030
"webview/context": [
@@ -37,7 +37,7 @@
3737
}
3838
},
3939
"gitlens.ai.aiRebaseUnpushed:graph": {
40-
"label": "AI Recompose unpushed commits (Preview)...",
40+
"label": "AI Recompose Unpushed Commits (Preview)",
4141
"icon": "$(sparkle)",
4242
"menus": {
4343
"webview/context": [
@@ -139,6 +139,19 @@
139139
]
140140
}
141141
},
142+
"gitlens.ai.explainUnpushed:graph": {
143+
"label": "Explain Unpushed Changes (Preview)",
144+
"icon": "$(sparkle)",
145+
"menus": {
146+
"webview/context": [
147+
{
148+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
149+
"group": "1_gitlens_actions_4",
150+
"order": 102
151+
}
152+
]
153+
}
154+
},
142155
"gitlens.ai.explainWip": {
143156
"label": "Explain Working Changes (Preview)...",
144157
"commandPalette": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"

package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6178,12 +6178,12 @@
61786178
},
61796179
{
61806180
"command": "gitlens.ai.aiRebaseBranch:graph",
6181-
"title": "AI Recompose branch commits (Preview)...",
6181+
"title": "AI Recompose Branch Commits (Preview)",
61826182
"icon": "$(sparkle)"
61836183
},
61846184
{
61856185
"command": "gitlens.ai.aiRebaseUnpushed:graph",
6186-
"title": "AI Recompose unpushed commits (Preview)...",
6186+
"title": "AI Recompose Unpushed Commits (Preview)",
61876187
"icon": "$(sparkle)"
61886188
},
61896189
{
@@ -6231,6 +6231,11 @@
62316231
"title": "Explain Changes (Preview)",
62326232
"icon": "$(sparkle)"
62336233
},
6234+
{
6235+
"command": "gitlens.ai.explainUnpushed:graph",
6236+
"title": "Explain Unpushed Changes (Preview)",
6237+
"icon": "$(sparkle)"
6238+
},
62346239
{
62356240
"command": "gitlens.ai.explainWip",
62366241
"title": "Explain Working Changes (Preview)...",
@@ -11013,6 +11018,10 @@
1101311018
"command": "gitlens.ai.explainStash:views",
1101411019
"when": "false"
1101511020
},
11021+
{
11022+
"command": "gitlens.ai.explainUnpushed:graph",
11023+
"when": "false"
11024+
},
1101611025
{
1101711026
"command": "gitlens.ai.explainWip",
1101811027
"when": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
@@ -23278,6 +23287,11 @@
2327823287
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/ && gitlens:action:createPullRequest && gitlens:repos:withRemotes",
2327923288
"group": "1_gitlens_actions_3@4"
2328023289
},
23290+
{
23291+
"command": "gitlens.ai.explainUnpushed:graph",
23292+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
23293+
"group": "1_gitlens_actions_4@102"
23294+
},
2328123295
{
2328223296
"command": "gitlens.ai.generateChangelogFrom:graph",
2328323297
"when": "webviewItem =~ /gitlens:(branch|tag)\\b/ && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",

src/commands/explainBranch.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { ExplainCommandBase } from './explainBase';
1616

1717
export interface ExplainBranchCommandArgs extends ExplainBaseArgs {
1818
ref?: string;
19+
baseBranch?: string;
1920
}
2021

2122
@command()
@@ -67,15 +68,25 @@ export class ExplainBranchCommand extends ExplainCommandBase {
6768
}
6869

6970
// Clarifying the base branch
70-
const baseBranchNameResult = await getBranchMergeTargetName(this.container, branch);
7171
let baseBranch;
72-
if (!baseBranchNameResult.paused) {
73-
baseBranch = await svc.branches.getBranch(baseBranchNameResult.value);
74-
}
75-
76-
if (!baseBranch) {
77-
void showGenericErrorMessage(`Unable to find the base branch for branch ${branch.name}.`);
78-
return;
72+
if (args.baseBranch) {
73+
// Use the provided base branch
74+
baseBranch = await svc.branches.getBranch(args.baseBranch);
75+
if (!baseBranch) {
76+
void showGenericErrorMessage(`Unable to find the specified base branch: ${args.baseBranch}`);
77+
return;
78+
}
79+
} else {
80+
// Fall back to automatic merge target detection
81+
const baseBranchNameResult = await getBranchMergeTargetName(this.container, branch);
82+
if (!baseBranchNameResult.paused) {
83+
baseBranch = await svc.branches.getBranch(baseBranchNameResult.value);
84+
}
85+
86+
if (!baseBranch) {
87+
void showGenericErrorMessage(`Unable to find the base branch for branch ${branch.name}.`);
88+
return;
89+
}
7990
}
8091

8192
// Get the diff between the branch and its upstream or base

src/constants.commands.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type ContributedCommands =
1212
| 'gitlens.ai.explainCommit:views'
1313
| 'gitlens.ai.explainStash:graph'
1414
| 'gitlens.ai.explainStash:views'
15+
| 'gitlens.ai.explainUnpushed:graph'
1516
| 'gitlens.ai.explainWip:graph'
1617
| 'gitlens.ai.explainWip:views'
1718
| 'gitlens.ai.feedback.helpful'

src/webviews/plus/graph/graphWebview.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
701701
this.copyWorkingChangesToWorktree,
702702
),
703703
this.host.registerWebviewCommand('gitlens.ai.generateCommitMessage:graph', this.generateCommitMessage),
704+
this.host.registerWebviewCommand('gitlens.ai.explainUnpushed:graph', this.aiExplainUnpushed),
704705
this.host.registerWebviewCommand('gitlens.ai.explainBranch:graph', this.explainBranch),
705706
this.host.registerWebviewCommand('gitlens.ai.explainCommit:graph', this.explainCommit),
706707
this.host.registerWebviewCommand('gitlens.ai.explainStash:graph', this.explainStash),
@@ -3896,6 +3897,25 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
38963897
});
38973898
}
38983899

3900+
@log()
3901+
private aiExplainUnpushed(item?: GraphItemContext) {
3902+
if (isGraphItemRefContext(item, 'branch')) {
3903+
const { ref } = item.webviewItemValue;
3904+
3905+
if (!ref.upstream) {
3906+
return Promise.resolve();
3907+
}
3908+
3909+
return executeCommand<ExplainBranchCommandArgs>('gitlens.ai.explainBranch', {
3910+
repoPath: ref.repoPath,
3911+
ref: ref.ref,
3912+
baseBranch: ref.upstream.name,
3913+
source: { source: 'graph', type: 'branch' },
3914+
});
3915+
}
3916+
3917+
return Promise.resolve();
3918+
}
38993919
@log()
39003920
private explainBranch(item?: GraphItemContext) {
39013921
const ref = this.getGraphItemRef(item, 'branch');

0 commit comments

Comments
 (0)