Skip to content

Commit e722657

Browse files
committed
Adds AI-powered explanation for unpushed branch changes on Graph View
Also adds more item context for new AI-assisted commands to explain unpushed changes (#4443, #4522)
1 parent ef09685 commit e722657

File tree

6 files changed

+70
-9
lines changed

6 files changed

+70
-9
lines changed

contributions.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@
113113
]
114114
}
115115
},
116+
"gitlens.ai.explainUnpushed:graph": {
117+
"label": "Explain Unpushed Changes (Preview)",
118+
"icon": "$(sparkle)",
119+
"menus": {
120+
"webview/context": [
121+
{
122+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
123+
"group": "1_gitlens_ai",
124+
"order": 20
125+
}
126+
]
127+
}
128+
},
116129
"gitlens.ai.explainWip": {
117130
"label": "Explain Working Changes (Preview)...",
118131
"commandPalette": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6251,6 +6251,11 @@
62516251
"title": "Explain Changes (Preview)",
62526252
"icon": "$(sparkle)"
62536253
},
6254+
{
6255+
"command": "gitlens.ai.explainUnpushed:graph",
6256+
"title": "Explain Unpushed Changes (Preview)",
6257+
"icon": "$(sparkle)"
6258+
},
62546259
{
62556260
"command": "gitlens.ai.explainWip",
62566261
"title": "Explain Working Changes (Preview)...",
@@ -11371,6 +11376,10 @@
1137111376
"command": "gitlens.ai.explainStash:views",
1137211377
"when": "false"
1137311378
},
11379+
{
11380+
"command": "gitlens.ai.explainUnpushed:graph",
11381+
"when": "false"
11382+
},
1137411383
{
1137511384
"command": "gitlens.ai.explainWip",
1137611385
"when": "gitlens:enabled && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled"
@@ -24162,6 +24171,11 @@
2416224171
"when": "webviewItem =~ /gitlens:branch\\b/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
2416324172
"group": "1_gitlens_ai@10"
2416424173
},
24174+
{
24175+
"command": "gitlens.ai.explainUnpushed:graph",
24176+
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+ahead\\b)/ && !listMultiSelection && !gitlens:readonly && !gitlens:untrusted && gitlens:gk:organization:ai:enabled",
24177+
"group": "1_gitlens_ai@20"
24178+
},
2416524179
{
2416624180
"command": "gitlens.graph.openBranchOnRemote",
2416724181
"when": "webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/ && gitlens:repos:withRemotes",

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/env/node/git/sub-providers/graph.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,9 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
359359
: branchIdOfMainWorktree === branchId
360360
? '+checkedout'
361361
: ''
362-
}${branch?.starred ? '+starred' : ''}`,
362+
}${branch?.starred ? '+starred' : ''}${branch?.upstream?.state.ahead ? '+ahead' : ''}${
363+
branch?.upstream?.state.behind ? '+behind' : ''
364+
}`,
363365
webviewItemValue: {
364366
type: 'branch',
365367
ref: createReference(tip, repoPath, {

src/webviews/plus/graph/graphWebview.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
719719
this.copyWorkingChangesToWorktree,
720720
),
721721
this.host.registerWebviewCommand('gitlens.ai.generateCommitMessage:graph', this.generateCommitMessage),
722+
this.host.registerWebviewCommand('gitlens.ai.explainUnpushed:graph', this.aiExplainUnpushed),
722723
this.host.registerWebviewCommand('gitlens.ai.explainBranch:graph', this.explainBranch),
723724
this.host.registerWebviewCommand('gitlens.ai.explainCommit:graph', this.explainCommit),
724725
this.host.registerWebviewCommand('gitlens.ai.explainStash:graph', this.explainStash),
@@ -3990,6 +3991,25 @@ export class GraphWebviewProvider implements WebviewProvider<State, State, Graph
39903991
});
39913992
}
39923993

3994+
@log()
3995+
private aiExplainUnpushed(item?: GraphItemContext) {
3996+
if (isGraphItemRefContext(item, 'branch')) {
3997+
const { ref } = item.webviewItemValue;
3998+
3999+
if (!ref.upstream) {
4000+
return Promise.resolve();
4001+
}
4002+
4003+
return executeCommand<ExplainBranchCommandArgs>('gitlens.ai.explainBranch', {
4004+
repoPath: ref.repoPath,
4005+
ref: ref.ref,
4006+
baseBranch: ref.upstream.name,
4007+
source: { source: 'graph', context: { type: 'branch' } },
4008+
});
4009+
}
4010+
4011+
return Promise.resolve();
4012+
}
39934013
@log()
39944014
private explainBranch(item?: GraphItemContext) {
39954015
const ref = this.getGraphItemRef(item, 'branch');

0 commit comments

Comments
 (0)