1.创建一个名字为rebase的js文件
#!/usr/bin/env node
const path = require('path');
const chalk = require('chalk');
const shell = require('shelljs');
const inquirer = require('inquirer');
const currentRepo = {
root: path.resolve(__dirname, '..'),
};
function error(str) {
console.log(chalk.red(`[Rabaser] ${str}`));
throw new Error(str);
}
function green(str) {
if (str) {
console.log(chalk.green(`[Rabaser] ${str}`));
}
}
function warn(str) {
console.log(chalk.yellow(`[Rabaser] ${str}`));
}
function line() {
console.log('');
}
function exec(str, successInfo) {
const res = shell.exec(str);
if (res.code !== 0) {
error(res.stderr);
} else {
green(successInfo);
green('====================');
return res;
}
return null;
}
async function rebase(repo, baseBranch) {
shell.cd(repo.root);
line();
green(`========== At ${repo.root} ==========`);
// Get current branch name
const workBranch = exec('git symbolic-ref --short -q HEAD')
.stdout.replace('
', '');
warn(`You are currently on branch ${workBranch}.`);
if (workBranch === 'master' || workBranch === 'pre') {
error(`You can not perform this operation on branch \`${workBranch}\`!!`);
}
await inquirer.prompt([{
type: 'input',
message: `You are trying to rebase branch ${workBranch} onto branch ${baseBranch}. Press any key to continue.`,
name: 'msg',
}]).then((answers) => answers.msg);
const res = exec('git status');
if (res.stdout.match('尚未暂存')) {
await inquirer.prompt([{
type: 'input',
message: '当前分支有尚未提交的修改,是否提交?',
name: 'msg',
}]).then((answers) => answers.msg);
exec('git add .');
exec('git commit -m "快速提交。"');
exec('git push');
}
const backupBranchPrefix = `${workBranch}-backup-9860-`;
try {
const backupBranchesStr = exec(`git branch | grep ${backupBranchPrefix}`);
if (backupBranchesStr) {
const backupBranches = backupBranchesStr.split('
').filter(str => str);
backupBranches.forEach(branchName => {
exec(`git branch -D ${branchName}`, `Deleted backup branch ${branchName}`);
});
}
} catch (e) {
warn('No backup branch exists.');
}
// Copy workbranch to a new branch as backup
const backupBranchName = `${backupBranchPrefix}${new Date().getTime()}`;
exec(`git branch ${backupBranchName}`, `Created backup branch ${backupBranchName}`);
// Switch to the base branch
exec(`git checkout ${baseBranch}`, `Switched to local branch ${baseBranch}`);
const out = exec('git status');
if (out.match('Changes not staged for') || out.match('Changes to be committed')) {
error('There are changes unsaved for base branch. Aborting.');
}
// Synchronize
exec(`git pull origin ${baseBranch}`, 'Synchronized local base branch with remote base branch.');
// Compare local base branch with remote base branch
warn('Remote base branch hash:');
const hashes = exec(`git rev-parse origin ${baseBranch}`).stdout.split('
').filter(str => str);
console.log(hashes);
const remoteBaseCurrentHash = hashes[hashes.length - 1];
warn('Local base branch hash:');
const localBaseHash = exec('git rev-parse HEAD').stdout.replace('
', '');
if (localBaseHash !== remoteBaseCurrentHash) {
exec(`git checkout ${workBranch}`);
error('Local base branch is not the same with remote base branch!! Aborting.');
}
// Switch to the target branch
exec(`git checkout ${workBranch}`);
try {
exec(`git rebase ${baseBranch} ${workBranch}`, 'Rebased successfully');
} catch (e) {
chalk.red('Conflicts occured in the rebase process. Resolve conflicts, execute "git add ." and "git rebase --continue" to finish rebase, then run this script again.');
throw new Error();
}
try {
let msg = await inquirer.prompt([{
type: 'input',
message: 'Input your commit message:',
name: 'msg',
}]).then((answers) => answers.msg);
if (!msg) msg = '快速提交。';
exec(`git reset ${localBaseHash}`);
exec('git add .', 'Added');
exec(`git commit -m "${msg || repo.msg}"`, 'Committed');
exec(`git push -f --set-upstream origin ${workBranch}`, `Caution: Pushed to \`origin ${workBranch}\` by force.`);
console.log('end');
} catch (e) {
const res = exec('git status').stdout;
if (
res.match('Your branch is behind')
|| res.match('Your branch is ahead of')
|| res.match('have diverged')
) {
exec(`git push -f --set-upstream origin ${workBranch}`, `Caution: Pushed to \`origin ${workBranch}\` by force.`);
}
if (res.match('Your branch is up to date')) {
warn('Nothing to push');
}
}
}
rebase(currentRepo, 'pre');
2.在package.json的scripts里面添加
"rebase:onto:pre": "node ./rebase.js"
3.在项目所在文件夹下执行rebase:onto:pre命令,即可执行rebase文件中的内容