Skip to content

Commit 889aa37

Browse files
committed
Auto-stash on pull
Closes #4296
1 parent 402bf3b commit 889aa37

File tree

9 files changed

+47
-52
lines changed

9 files changed

+47
-52
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
66

77
## [Unreleased]
88

9+
### Changed
10+
11+
- Automatically stashes (and pops) uncommitted changes on Pull ([#4296](https://github.com/gitkraken/vscode-gitlens/issues/4296))
12+
913
## [17.1.1] - 2025-05-21
1014

1115
### Fixed

src/env/node/git/git.ts

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,12 @@ import { CancelledRunError, RunError } from './shell.errors';
5656
const emptyArray: readonly any[] = Object.freeze([]);
5757
const emptyObj = Object.freeze({});
5858

59-
const gitBranchDefaultConfigs = Object.freeze(['-c', 'color.branch=false']);
60-
export const gitDiffDefaultConfigs = Object.freeze(['-c', 'color.diff=false']);
61-
export const gitLogDefaultConfigs = Object.freeze(['-c', 'log.showSignature=false']);
62-
export const gitLogDefaultConfigsWithFiles = Object.freeze([
63-
'-c',
64-
'log.showSignature=false',
65-
'-c',
66-
'diff.renameLimit=0',
67-
]);
68-
const gitStatusDefaultConfigs = Object.freeze(['-c', 'color.status=false']);
59+
export const gitConfigsBranch = ['-c', 'color.branch=false'] as const;
60+
export const gitConfigsDiff = ['-c', 'color.diff=false'] as const;
61+
export const gitConfigsLog = ['-c', 'log.showSignature=false'] as const;
62+
export const gitConfigsLogWithFiles = ['-c', 'log.showSignature=false', '-c', 'diff.renameLimit=0'] as const;
63+
export const gitConfigsPull = ['-c', 'merge.autoStash=true', '-c', 'rebase.autoStash=true'] as const;
64+
export const gitConfigsStatus = ['-c', 'color.status=false'] as const;
6965

7066
export const maxGitCliLength = 30000;
7167

@@ -740,7 +736,7 @@ export class Git implements Disposable {
740736
{
741737
cwd: repoPath,
742738
cancellation: cancellation,
743-
configs: gitBranchDefaultConfigs,
739+
configs: gitConfigsBranch,
744740
errors: GitErrorHandling.Ignore,
745741
},
746742
...params,
@@ -852,7 +848,7 @@ export class Git implements Disposable {
852848

853849
try {
854850
const result = await this.exec(
855-
{ cwd: repoPath, configs: gitDiffDefaultConfigs, encoding: options?.encoding },
851+
{ cwd: repoPath, configs: gitConfigsDiff, encoding: options?.encoding },
856852
...params,
857853
'--',
858854
fileName,
@@ -904,7 +900,7 @@ export class Git implements Disposable {
904900
const result = await this.exec(
905901
{
906902
cwd: repoPath,
907-
configs: gitDiffDefaultConfigs,
903+
configs: gitConfigsDiff,
908904
encoding: options?.encoding,
909905
stdin: contents,
910906
},
@@ -1070,7 +1066,7 @@ export class Git implements Disposable {
10701066
}
10711067

10721068
try {
1073-
void (await this.exec({ cwd: repoPath }, ...params));
1069+
void (await this.exec({ cwd: repoPath, configs: gitConfigsPull }, ...params));
10741070
} catch (ex) {
10751071
const msg: string = ex?.toString() ?? '';
10761072
let reason: PullErrorReason = PullErrorReason.Other;
@@ -1207,7 +1203,7 @@ export class Git implements Disposable {
12071203
{
12081204
cwd: repoPath,
12091205
cancellation: cancellation,
1210-
configs: gitLogDefaultConfigs,
1206+
configs: gitConfigsLog,
12111207
errors: GitErrorHandling.Ignore,
12121208
},
12131209
'log',
@@ -1409,7 +1405,7 @@ export class Git implements Disposable {
14091405
if (isUncommitted(ref)) throw new Error(`ref=${ref} is uncommitted`);
14101406

14111407
const opts: GitCommandOptions = {
1412-
configs: gitLogDefaultConfigs,
1408+
configs: gitConfigsLog,
14131409
cwd: root,
14141410
encoding: options?.encoding ?? 'utf8',
14151411
errors: GitErrorHandling.Throw,
@@ -1528,7 +1524,7 @@ export class Git implements Disposable {
15281524
{
15291525
cwd: repoPath,
15301526
cancellation: cancellation,
1531-
configs: gitStatusDefaultConfigs,
1527+
configs: gitConfigsStatus,
15321528
env: { GIT_OPTIONAL_LOCKS: '0' },
15331529
},
15341530
...params,

src/env/node/git/sub-providers/branches.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { normalizePath } from '../../../../system/path';
3939
import { getSettledValue } from '../../../../system/promise';
4040
import { maybeStopWatch } from '../../../../system/stopwatch';
4141
import type { Git } from '../git';
42-
import { GitError, GitErrors, gitLogDefaultConfigs } from '../git';
42+
import { gitConfigsLog, GitError, GitErrors } from '../git';
4343
import type { LocalGitProvider } from '../localGitProvider';
4444

4545
const emptyPagedResult: PagedResult<any> = Object.freeze({ values: [] });
@@ -92,7 +92,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
9292
{
9393
cwd: repoPath,
9494
cancellation: cancellation,
95-
configs: gitLogDefaultConfigs,
95+
configs: gitConfigsLog,
9696
errors: GitErrorHandling.Ignore,
9797
},
9898
'log',

src/env/node/git/sub-providers/commits.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import { isFolderGlob, stripFolderGlob } from '../../../../system/path';
5555
import type { CachedLog, TrackedGitDocument } from '../../../../trackers/trackedDocument';
5656
import { GitDocumentState } from '../../../../trackers/trackedDocument';
5757
import type { Git, GitResult } from '../git';
58-
import { GitErrors, gitLogDefaultConfigs, gitLogDefaultConfigsWithFiles } from '../git';
58+
import { gitConfigsLog, gitConfigsLogWithFiles, GitErrors } from '../git';
5959
import type { LocalGitProviderInternal } from '../localGitProvider';
6060
import { convertStashesToStdin } from './stash';
6161

@@ -171,7 +171,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
171171
async getCommitFiles(repoPath: string, rev: string, cancellation?: CancellationToken): Promise<GitFileChange[]> {
172172
const parser = getShaAndFilesAndStatsLogParser();
173173
const result = await this.git.exec(
174-
{ cwd: repoPath, cancellation: cancellation, configs: gitLogDefaultConfigs },
174+
{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsLog },
175175
'log',
176176
...parser.arguments,
177177
'-n1',
@@ -260,7 +260,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
260260

261261
try {
262262
const result = await this.git.exec(
263-
{ cwd: repoPath, cancellation: cancellation, configs: gitLogDefaultConfigs },
263+
{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsLog },
264264
'log',
265265
...args,
266266
);
@@ -513,7 +513,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
513513
const cmdOpts: GitCommandOptions = {
514514
cwd: repoPath,
515515
cancellation: cancellation,
516-
configs: gitLogDefaultConfigsWithFiles,
516+
configs: gitConfigsLogWithFiles,
517517
stdin: stdin,
518518
};
519519
let { commits, count, countStashChildCommits } = await parseCommits(
@@ -983,7 +983,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
983983
}
984984

985985
const result = await this.git.exec(
986-
{ cwd: repoPath, cancellation: cancellation, configs: gitLogDefaultConfigs },
986+
{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsLog },
987987
'log',
988988
...args,
989989
);
@@ -1017,7 +1017,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
10171017
}
10181018

10191019
const result = await this.git.exec(
1020-
{ cwd: repoPath, cancellation: cancellation, configs: gitLogDefaultConfigs },
1020+
{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsLog },
10211021
'log',
10221022
...parser.arguments,
10231023
'--follow',
@@ -1143,7 +1143,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
11431143
{
11441144
cwd: repoPath,
11451145
cancellation: cancellation,
1146-
configs: ['-C', repoPath, ...gitLogDefaultConfigs],
1146+
configs: ['-C', repoPath, ...gitConfigsLog],
11471147
stdin: stdin,
11481148
},
11491149
...args,

src/env/node/git/sub-providers/contributors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { normalizePath } from '../../../../system/path';
1717
import type { Cancellable } from '../../../../system/promiseCache';
1818
import { PromiseCache } from '../../../../system/promiseCache';
1919
import type { Git } from '../git';
20-
import { gitLogDefaultConfigs } from '../git';
20+
import { gitConfigsLog } from '../git';
2121
import type { LocalGitProvider } from '../localGitProvider';
2222

2323
export class ContributorsGitSubProvider implements GitContributorsSubProvider {
@@ -87,7 +87,7 @@ export class ContributorsGitSubProvider implements GitContributorsSubProvider {
8787
const signal = timeout ? AbortSignal.timeout(timeout) : undefined;
8888

8989
const stream = this.git.stream(
90-
{ cwd: repoPath, cancellation: cancellation, configs: gitLogDefaultConfigs, signal: signal },
90+
{ cwd: repoPath, cancellation: cancellation, configs: gitConfigsLog, signal: signal },
9191
'log',
9292
...args,
9393
);

src/env/node/git/sub-providers/diff.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { first } from '../../../../system/iterable';
3535
import { Logger } from '../../../../system/logger';
3636
import { getLogScope } from '../../../../system/logger.scope';
3737
import type { Git, GitResult } from '../git';
38-
import { gitDiffDefaultConfigs, GitErrors, gitLogDefaultConfigs } from '../git';
38+
import { gitConfigsDiff, gitConfigsLog, GitErrors } from '../git';
3939
import type { LocalGitProvider } from '../localGitProvider';
4040

4141
export class DiffGitSubProvider implements GitDiffSubProvider {
@@ -67,7 +67,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
6767

6868
try {
6969
const result = await this.git.exec(
70-
{ cwd: repoPath, configs: gitDiffDefaultConfigs },
70+
{ cwd: repoPath, configs: gitConfigsDiff },
7171
'diff',
7272
'--shortstat',
7373
'--no-ext-diff',
@@ -137,7 +137,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
137137
let result;
138138
try {
139139
result = await this.git.exec(
140-
{ cwd: repoPath, configs: gitLogDefaultConfigs, errors: GitErrorHandling.Throw },
140+
{ cwd: repoPath, configs: gitConfigsLog, errors: GitErrorHandling.Throw },
141141
'diff',
142142
...args,
143143
args.includes('--') ? undefined : '--',
@@ -159,7 +159,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
159159
@log({ args: { 1: false } })
160160
async getDiffFiles(repoPath: string, contents: string): Promise<GitDiffFiles | undefined> {
161161
const result = await this.git.exec(
162-
{ cwd: repoPath, configs: gitLogDefaultConfigs, stdin: contents },
162+
{ cwd: repoPath, configs: gitConfigsLog, stdin: contents },
163163
'apply',
164164
'--numstat',
165165
'--summary',
@@ -185,7 +185,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
185185
const similarityThreshold =
186186
options?.similarityThreshold ?? configuration.get('advanced.similarityThreshold') ?? undefined;
187187
const result = await this.git.exec(
188-
{ cwd: repoPath, configs: gitDiffDefaultConfigs },
188+
{ cwd: repoPath, configs: gitConfigsDiff },
189189
'diff',
190190
'--name-status',
191191
`-M${similarityThreshold == null ? '' : `${similarityThreshold}%`}`,
@@ -263,7 +263,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
263263
// Follow file history and specify the file path
264264
args.push('--follow', '--', relativePath);
265265

266-
const result = await this.git.exec({ cwd: repoPath, configs: gitLogDefaultConfigs }, ...args);
266+
const result = await this.git.exec({ cwd: repoPath, configs: gitConfigsLog }, ...args);
267267

268268
let currentSha;
269269
let currentPath;
@@ -487,7 +487,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
487487

488488
args.push('--follow', rev!, '--', relativePath);
489489

490-
const result = await this.git.exec({ cwd: repoPath, configs: gitLogDefaultConfigs }, ...args);
490+
const result = await this.git.exec({ cwd: repoPath, configs: gitConfigsLog }, ...args);
491491

492492
let previousSha;
493493
let previousPath;
@@ -603,7 +603,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
603603

604604
let result: GitResult<string>;
605605
try {
606-
result = await this.git.exec({ cwd: repoPath, configs: gitLogDefaultConfigs }, ...args);
606+
result = await this.git.exec({ cwd: repoPath, configs: gitConfigsLog }, ...args);
607607
} catch (ex) {
608608
if (rev && !isUncommittedStaged(rev)) throw ex;
609609

@@ -624,7 +624,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
624624
};
625625

626626
args.splice(index, 1, `-L${range.startLine},${range.endLine}:${relativePath}`);
627-
result = await this.git.exec({ cwd: repoPath, configs: gitLogDefaultConfigs }, ...args);
627+
result = await this.git.exec({ cwd: repoPath, configs: gitConfigsLog }, ...args);
628628
}
629629

630630
let currentRange;
@@ -808,7 +808,7 @@ export async function findPathStatusChanged(
808808
const ordering = options?.ordering ?? configuration.get('advanced.commitOrdering');
809809

810810
const result = await git.exec(
811-
{ cwd: repoPath, configs: gitLogDefaultConfigs },
811+
{ cwd: repoPath, configs: gitConfigsLog },
812812
'log',
813813
...parser.arguments,
814814
ordering ? `--${ordering}-order` : undefined,

src/env/node/git/sub-providers/graph.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import type {
5959
GraphTagContextValue,
6060
} from '../../../../webviews/plus/graph/protocol';
6161
import type { Git } from '../git';
62-
import { gitLogDefaultConfigs } from '../git';
62+
import { gitConfigsLog } from '../git';
6363
import type { LocalGitProvider } from '../localGitProvider';
6464
import { convertStashesToStdin } from './stash';
6565

@@ -94,7 +94,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
9494
const [shaResult, stashResult, branchesResult, remotesResult, currentUserResult, worktreesResult] =
9595
await Promise.allSettled([
9696
this.git.exec(
97-
{ cwd: repoPath, configs: gitLogDefaultConfigs },
97+
{ cwd: repoPath, configs: gitConfigsLog },
9898
'log',
9999
...shaParser.arguments,
100100
'-n1',
@@ -171,7 +171,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
171171
using _disposable = mixinDisposable(cancellation?.onCancellationRequested(() => aborter.abort()));
172172

173173
const stream = this.git.stream(
174-
{ cwd: repoPath, configs: gitLogDefaultConfigs, signal: aborter.signal, stdin: stdin },
174+
{ cwd: repoPath, configs: gitConfigsLog, signal: aborter.signal, stdin: stdin },
175175
...args,
176176
cursor?.skip ? `--skip=${cursor.skip}` : undefined,
177177
'--',
@@ -546,7 +546,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
546546
args.push(`--${ordering}-order`, '--all');
547547

548548
const statsResult = await this.git.exec(
549-
{ cwd: repoPath, configs: gitLogDefaultConfigs, stdin: stdin },
549+
{ cwd: repoPath, configs: gitConfigsLog, stdin: stdin },
550550
'log',
551551
stdin ? '--stdin' : undefined,
552552
...args,
@@ -704,7 +704,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
704704
{
705705
cwd: repoPath,
706706
cancellation: cancellation,
707-
configs: ['-C', repoPath, ...gitLogDefaultConfigs],
707+
configs: ['-C', repoPath, ...gitConfigsLog],
708708
signal: aborter.signal,
709709
stdin: stdin,
710710
},

src/env/node/git/sub-providers/patch.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { log } from '../../../../system/decorators/log';
1515
import { Logger } from '../../../../system/logger';
1616
import { getLogScope } from '../../../../system/logger.scope';
1717
import type { Git } from '../git';
18-
import { gitLogDefaultConfigs } from '../git';
18+
import { gitConfigsLog } from '../git';
1919
import type { LocalGitProvider } from '../localGitProvider';
2020

2121
export class PatchGitSubProvider implements GitPatchSubProvider {
@@ -211,7 +211,7 @@ export class PatchGitSubProvider implements GitPatchSubProvider {
211211
try {
212212
// Apply the patch to our temp index, without touching the working directory
213213
await this.git.exec(
214-
{ cwd: repoPath, configs: gitLogDefaultConfigs, env: env, stdin: patch },
214+
{ cwd: repoPath, configs: gitConfigsLog, env: env, stdin: patch },
215215
'apply',
216216
'--cached',
217217
'-',
@@ -237,12 +237,7 @@ export class PatchGitSubProvider implements GitPatchSubProvider {
237237
@log({ args: { 1: false } })
238238
async validatePatch(repoPath: string | undefined, contents: string): Promise<boolean> {
239239
try {
240-
await this.git.exec(
241-
{ cwd: repoPath, configs: gitLogDefaultConfigs, stdin: contents },
242-
'apply',
243-
'--check',
244-
'-',
245-
);
240+
await this.git.exec({ cwd: repoPath, configs: gitConfigsLog, stdin: contents }, 'apply', '--check', '-');
246241
return true;
247242
} catch (ex) {
248243
if (ex instanceof Error && ex.message) {

src/git/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ export class PullError extends Error {
258258
reason = messageOrReason;
259259
switch (reason) {
260260
case PullErrorReason.Conflict:
261-
message = `${baseMessage} due to conflicts.`;
261+
message = `Unable to complete pull due to conflicts which must be resolved.`;
262262
break;
263263
case PullErrorReason.GitIdentity:
264264
message = `${baseMessage} because you have not yet set up your Git identity.`;

0 commit comments

Comments
 (0)