stash and restore uncommitted changes

This commit is contained in:
Peter Evans 2022-11-29 14:48:18 +09:00
parent 87923ad652
commit fa545b74a7
4 changed files with 141 additions and 6 deletions

View file

@ -1150,6 +1150,50 @@ describe('create-or-update-branch tests', () => {
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
})
it('tests create consecutive branches with restored changes from stash', async () => {
const BRANCHA = `${BRANCH}-a`
const BRANCHB = `${BRANCH}-b`
// Create tracked and untracked file changes
const changes = await createChanges()
const commitMessage = uuidv4()
const resultA = await createOrUpdateBranch(
git,
commitMessage,
'',
BRANCHA,
REMOTE_NAME,
false,
['a']
)
const resultB = await createOrUpdateBranch(
git,
commitMessage,
'',
BRANCHB,
REMOTE_NAME,
false,
['b']
)
await git.checkout(BRANCHA)
expect(resultA.action).toEqual('created')
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
expect(
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
).toBeTruthy()
await git.checkout(BRANCHB)
expect(resultB.action).toEqual('created')
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
expect(
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
).toBeTruthy()
// Delete the local branches
await git.checkout(DEFAULT_BRANCH)
await git.exec(['branch', '--delete', '--force', BRANCHA])
await git.exec(['branch', '--delete', '--force', BRANCHB])
})
// Working Base is Not Base (WBNB)
it('tests no changes resulting in no new branch being created (WBNB)', async () => {
@ -2132,4 +2176,52 @@ describe('create-or-update-branch tests', () => {
// The action cannot successfully create the branch
expect(result.action).toEqual('none')
})
it('tests create consecutive branches with restored changes from stash in detached HEAD state (WBNR)', async () => {
// Checkout the HEAD commit SHA
const headSha = await git.revParse('HEAD')
await git.checkout(headSha)
const BRANCHA = `${BRANCH}-a`
const BRANCHB = `${BRANCH}-b`
// Create tracked and untracked file changes
const changes = await createChanges()
const commitMessage = uuidv4()
const resultA = await createOrUpdateBranch(
git,
commitMessage,
BASE,
BRANCHA,
REMOTE_NAME,
false,
['a']
)
const resultB = await createOrUpdateBranch(
git,
commitMessage,
BASE,
BRANCHB,
REMOTE_NAME,
false,
['b']
)
await git.checkout(BRANCHA)
expect(resultA.action).toEqual('created')
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
expect(
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
).toBeTruthy()
await git.checkout(BRANCHB)
expect(resultB.action).toEqual('created')
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
expect(
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
).toBeTruthy()
// Delete the local branches
await git.checkout(DEFAULT_BRANCH)
await git.exec(['branch', '--delete', '--force', BRANCHA])
await git.exec(['branch', '--delete', '--force', BRANCHB])
})
})

28
dist/index.js vendored
View file

@ -158,9 +158,8 @@ function createOrUpdateBranch(git, commitMessage, base, branch, branchRemoteName
throw new Error(`Unexpected error: ${commitResult.stderr}`);
}
}
// Remove uncommitted tracked and untracked changes
yield git.exec(['reset', '--hard']);
yield git.exec(['clean', '-f', '-d']);
// Stash any uncommitted tracked and untracked changes
const stashed = yield git.stashPush(['--include-untracked']);
// Perform fetch and reset the working base
// Commits made during the workflow will be removed
if (workingBaseType == WorkingBaseType.Branch) {
@ -260,6 +259,10 @@ function createOrUpdateBranch(git, commitMessage, base, branch, branchRemoteName
yield git.exec(['branch', '--delete', '--force', tempBranch]);
// Checkout the working base to leave the local repository as it was found
yield git.checkout(workingBase);
// Restore any stashed changes
if (stashed) {
yield git.stashPop();
}
return result;
});
}
@ -844,6 +847,25 @@ class GitCommandManager {
return output.stdout.trim();
});
}
stashPush(options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['stash', 'push'];
if (options) {
args.push(...options);
}
const output = yield this.exec(args);
return output.stdout.trim() !== 'No local changes to save';
});
}
stashPop(options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['stash', 'pop'];
if (options) {
args.push(...options);
}
yield this.exec(args);
});
}
status(options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['status'];

View file

@ -170,9 +170,8 @@ export async function createOrUpdateBranch(
}
}
// Remove uncommitted tracked and untracked changes
await git.exec(['reset', '--hard'])
await git.exec(['clean', '-f', '-d'])
// Stash any uncommitted tracked and untracked changes
const stashed = await git.stashPush(['--include-untracked'])
// Perform fetch and reset the working base
// Commits made during the workflow will be removed
@ -293,5 +292,10 @@ export async function createOrUpdateBranch(
// Checkout the working base to leave the local repository as it was found
await git.checkout(workingBase)
// Restore any stashed changes
if (stashed) {
await git.stashPop()
}
return result
}

View file

@ -210,6 +210,23 @@ export class GitCommandManager {
return output.stdout.trim()
}
async stashPush(options?: string[]): Promise<boolean> {
const args = ['stash', 'push']
if (options) {
args.push(...options)
}
const output = await this.exec(args)
return output.stdout.trim() !== 'No local changes to save'
}
async stashPop(options?: string[]): Promise<void> {
const args = ['stash', 'pop']
if (options) {
args.push(...options)
}
await this.exec(args)
}
async status(options?: string[]): Promise<string> {
const args = ['status']
if (options) {