Git - improve reference comparison commands (#274143)

* Git - improve compare commands

* Remove an extra check

* Fix bad manual merge
This commit is contained in:
Ladislau Szomoru
2025-10-30 17:00:30 +00:00
committed by GitHub
parent a4f5e37711
commit f46638bfc7
3 changed files with 63 additions and 53 deletions

View File

@@ -1005,6 +1005,12 @@
"category": "Git",
"enablement": "!operationInProgress"
},
{
"command": "git.graph.compareWithRemote",
"title": "%command.graphCompareWithRemote%",
"category": "Git",
"enablement": "!operationInProgress && scmCurrentHistoryItemRefHasRemote"
},
{
"command": "git.graph.compareWithMergeBase",
"title": "%command.graphCompareWithMergeBase%",
@@ -1622,6 +1628,10 @@
"command": "git.graph.compareWithMergeBase",
"when": "false"
},
{
"command": "git.graph.compareWithRemote",
"when": "false"
},
{
"command": "git.diff.stageHunk",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && diffEditorOriginalUri =~ /^git\\:.*%22ref%22%3A%22~%22%7D$/"
@@ -2264,15 +2274,20 @@
"group": "4_modify@1"
},
{
"command": "git.graph.compareRef",
"command": "git.graph.compareWithRemote",
"when": "scmProvider == git",
"group": "5_compare@1"
},
{
"command": "git.graph.compareWithMergeBase",
"when": "scmProvider == git && scmHistoryItemHasCurrentHistoryItemRef",
"when": "scmProvider == git",
"group": "5_compare@2"
},
{
"command": "git.graph.compareRef",
"when": "scmProvider == git",
"group": "5_compare@3"
},
{
"command": "git.copyCommitId",
"when": "scmProvider == git && !listMultiSelection",

View File

@@ -137,8 +137,9 @@
"command.graphCherryPick": "Cherry Pick",
"command.graphDeleteBranch": "Delete Branch",
"command.graphDeleteTag": "Delete Tag",
"command.graphCompareRef": "Compare With...",
"command.graphCompareWithMergeBase": "Compare With Merge Base",
"command.graphCompareRef": "Compare with...",
"command.graphCompareWithMergeBase": "Compare with Merge Base",
"command.graphCompareWithRemote": "Compare with Remote",
"command.blameToggleEditorDecoration": "Toggle Git Blame Editor Decoration",
"command.blameToggleStatusBarItem": "Toggle Git Blame Status Bar Item",
"command.api.getRepositories": "Get Repositories",

View File

@@ -5,7 +5,7 @@
import * as os from 'os';
import * as path from 'path';
import { Command, commands, Disposable, MessageOptions, Position, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation, languages, SourceControlHistoryItemRef } from 'vscode';
import { Command, commands, Disposable, MessageOptions, Position, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation, languages } from 'vscode';
import TelemetryReporter from '@vscode/extension-telemetry';
import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator';
import { ForcePushMode, GitErrorCodes, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote, Branch, Ref } from './api/git';
@@ -3109,6 +3109,30 @@ export class CommandCenter {
await this._deleteBranch(repository, remoteName, refName, { remote: true });
}
@command('git.graph.compareWithRemote', { repository: true })
async compareWithRemote(repository: Repository, historyItem?: SourceControlHistoryItem): Promise<void> {
if (!historyItem || !repository.historyProvider.currentHistoryItemRemoteRef) {
return;
}
await this._openChangesBetweenRefs(
repository,
repository.historyProvider.currentHistoryItemRemoteRef.name,
historyItem);
}
@command('git.graph.compareWithMergeBase', { repository: true })
async compareWithMergeBase(repository: Repository, historyItem?: SourceControlHistoryItem): Promise<void> {
if (!historyItem || !repository.historyProvider.currentHistoryItemBaseRef) {
return;
}
await this._openChangesBetweenRefs(
repository,
repository.historyProvider.currentHistoryItemBaseRef.name,
historyItem);
}
@command('git.graph.compareRef', { repository: true })
async compareBranch(repository: Repository, historyItem?: SourceControlHistoryItem): Promise<void> {
if (!repository || !historyItem) {
@@ -3137,68 +3161,38 @@ export class CommandCenter {
return;
}
if (historyItem.id === sourceRef.ref.commit) {
window.showInformationMessage(l10n.t('The selected references are the same.'));
return;
}
const sourceCommit = sourceRef.ref.commit;
try {
const changes = await repository.diffBetween2(sourceCommit, historyItem.id);
if (changes.length === 0) {
window.showInformationMessage(l10n.t('The selected references have no differences.'));
return;
}
const resources = changes.map(change => toMultiFileDiffEditorUris(change, sourceCommit, historyItem.id));
const title = `${sourceRef.ref.name ?? sourceCommit}${historyItem.references?.[0].name ?? historyItem.id}`;
const multiDiffSourceUri = Uri.from({
scheme: 'git-ref-compare',
path: `${repository.root}/${sourceCommit}..${historyItem.id}`
});
await commands.executeCommand('_workbench.openMultiDiffEditor', {
multiDiffSourceUri,
title,
resources
});
} catch (err) {
window.showErrorMessage(l10n.t('Failed to compare references "{0}" and "{1}": {2}', sourceCommit, historyItem.id, err.message));
}
}
@command('git.graph.compareWithMergeBase', { repository: true })
async compareWithMergeBase(repository: Repository): Promise<void> {
await this._openChangesBetweenRefs(
repository,
repository.historyProvider.currentHistoryItemBaseRef,
repository.historyProvider.currentHistoryItemRef);
sourceRef.ref.name,
historyItem);
}
private async _openChangesBetweenRefs(
repository: Repository,
ref1: SourceControlHistoryItemRef | undefined,
ref2: SourceControlHistoryItemRef | undefined
): Promise<void> {
if (!repository || !ref1 || !ref2) {
private async _openChangesBetweenRefs(repository: Repository, ref: string | undefined, historyItem: SourceControlHistoryItem | undefined): Promise<void> {
if (!repository || !ref || !historyItem) {
return;
}
const ref2 = historyItem.references?.length
? historyItem.references[0].name
: historyItem.id;
try {
const changes = await repository.diffBetween2(ref1.id, ref2.id);
const changes = await repository.diffBetween2(ref, historyItem.id);
if (changes.length === 0) {
window.showInformationMessage(l10n.t('There are no changes between "{0}" and "{1}".', ref1.name, ref2.name));
window.showInformationMessage(l10n.t('There are no changes between "{0}" and "{1}".', ref, ref2));
return;
}
const resources = changes.map(change => toMultiFileDiffEditorUris(change, ref1.id, ref2.id));
const title = `${ref1.name}${ref2.name}`;
const refDisplayName = historyItem.references?.length
? historyItem.references[0].name
: `${historyItem.displayId || historyItem.id} - ${historyItem.subject}`;
const resources = changes.map(change => toMultiFileDiffEditorUris(change, ref, ref2));
const title = `${ref}${refDisplayName}`;
const multiDiffSourceUri = Uri.from({
scheme: 'git-ref-compare',
path: `${repository.root}/${ref1.id}..${ref2.id}`
path: `${repository.root}/${ref}..${ref2}`
});
await commands.executeCommand('_workbench.openMultiDiffEditor', {
@@ -3207,7 +3201,7 @@ export class CommandCenter {
resources
});
} catch (err) {
window.showErrorMessage(l10n.t('Failed to open changes between "{0}" and "{1}": {2}', ref1.name, ref2.name, err.message));
window.showErrorMessage(l10n.t('Failed to open changes between "{0}" and "{1}": {2}', ref, ref2, err.message));
}
}