Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase current branch onto another branch #108913

Merged
merged 4 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions extensions/git/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@
"title": "%command.merge%",
"category": "Git"
},
{
"command": "git.rebaseOnto",
"title": "%command.rebaseOnto%",
"category": "Git"
},
{
"command": "git.createTag",
"title": "%command.createTag%",
Expand Down Expand Up @@ -703,6 +708,10 @@
"command": "git.merge",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
},
{
"command": "git.rebaseOnto",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
},
{
"command": "git.createTag",
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
Expand Down Expand Up @@ -1433,6 +1442,9 @@
{
"command": "git.merge"
},
{
"command": "git.rebaseOnto"
},
{
"command": "git.branch"
},
Expand Down
1 change: 1 addition & 0 deletions extensions/git/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"command.deleteBranch": "Delete Branch...",
"command.renameBranch": "Rename Branch...",
"command.merge": "Merge Branch...",
"command.rebaseOnto": "Rebase Branch Onto...",
"command.createTag": "Create Tag",
"command.deleteTag": "Delete Tag",
"command.fetch": "Fetch",
Expand Down
37 changes: 37 additions & 0 deletions extensions/git/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ class MergeItem implements QuickPickItem {
}
}

class RebaseOntoItem implements QuickPickItem {

get label(): string { return this.ref.name || ''; }
get description(): string { return this.ref.name || ''; }

constructor(protected ref: Ref) { }

async run(repository: Repository): Promise<void> {
await repository.rebaseOnto(repository.HEAD, this.ref);
}
}

class CreateBranchItem implements QuickPickItem {

constructor(private cc: CommandCenter) { }
Expand Down Expand Up @@ -1848,6 +1860,31 @@ export class CommandCenter {
await choice.run(repository);
}

@command('git.rebaseOnto', { repository: true })
async rebaseOnto(repository: Repository): Promise<void> {
const config = workspace.getConfiguration('git');
const checkoutType = config.get<string>('checkoutType') || 'all';
const includeRemotes = checkoutType === 'all' || checkoutType === 'remote';

const heads = repository.refs.filter(ref => ref.type === RefType.Head)
.filter(ref => ref.name || ref.commit)
.map(ref => new RebaseOntoItem(ref as Branch));

const remoteHeads = (includeRemotes ? repository.refs.filter(ref => ref.type === RefType.RemoteHead) : [])
.filter(ref => ref.name || ref.commit)
.map(ref => new RebaseOntoItem(ref as Branch));

const picks = [...heads, ...remoteHeads];
const placeHolder = localize('select a branch to rebase onto', 'Select a branch to rebase onto');
const choice = await window.showQuickPick<RebaseOntoItem>(picks, { placeHolder });

if (!choice) {
return;
}

await choice.run(repository);
}

@command('git.createTag', { repository: true })
async createTag(repository: Repository): Promise<void> {
const inputTagName = await window.showInputBox({
Expand Down
18 changes: 18 additions & 0 deletions extensions/git/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,24 @@ export class Repository {
}
}

async rebase(branch: string, options: PullOptions = {}): Promise<void> {
const args = ['rebase'];

args.push(branch);

try {
await this.run(args, options);
} catch (err) {
if (/^CONFLICT \([^)]+\): \b/m.test(err.stdout || '')) {
err.gitErrorCode = GitErrorCodes.Conflict;
} else if (/cannot rebase onto multiple branches/i.test(err.stderr || '')) {
err.gitErrorCode = GitErrorCodes.CantRebaseMultipleBranches;
}

throw err;
}
}

async push(remote?: string, name?: string, setUpstream: boolean = false, tags = false, forcePushMode?: ForcePushMode): Promise<void> {
const args = ['push'];

Expand Down
13 changes: 13 additions & 0 deletions extensions/git/src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export const enum Operation {
RenameBranch = 'RenameBranch',
DeleteRef = 'DeleteRef',
Merge = 'Merge',
Rebase = 'Rebase',
Ignore = 'Ignore',
Tag = 'Tag',
DeleteTag = 'DeleteTag',
Expand Down Expand Up @@ -1067,6 +1068,10 @@ export class Repository implements Disposable {
await this.run(Operation.Merge, () => this.repository.merge(ref));
}

async rebase(branch: string): Promise<void> {
await this.run(Operation.Rebase, () => this.repository.rebase(branch));
}

async tag(name: string, message?: string): Promise<void> {
await this.run(Operation.Tag, () => this.repository.tag(name, message));
}
Expand Down Expand Up @@ -1143,6 +1148,14 @@ export class Repository implements Disposable {
return this.pullFrom(true, remote, branch);
}

@throttle
async rebaseOnto(head: Branch | undefined, branch: Branch | undefined): Promise<void> {
if (head?.name && branch?.name) {
await this.checkout(branch.name);
await this.rebase(head.name);
}
}

@throttle
async pull(head?: Branch, unshallow?: boolean): Promise<void> {
let remote: string | undefined;
Expand Down