Last active
September 3, 2018 10:06
-
-
Save DAB0mB/51d2f1ae5f71e13733b9b476ad0d9f9c to your computer and use it in GitHub Desktop.
usage: $ ./git-remove.js <anchor> <amount>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const execa = require('execa') | |
const fs = require('fs') | |
const tmp = require('tmp') | |
// Main | |
{ | |
const [anchor, amount = 1] = process.argv.slice(-2).map(Number) | |
gitRebaseInteractive(anchor, function (operations, amount) { | |
operations = operations | |
// Replace comments | |
.replace(/#.*/g, '') | |
// Each line would be a cell | |
.split('\n') | |
// Get rid of empty lines | |
.filter(Boolean) | |
// Commits we would like to drop | |
const dropOperations = operations | |
.slice(0, amount) | |
.map(operation => operation.replace('pick', 'drop')) | |
// Commits we would like to pick | |
const pickOperations = operations.slice(amount) | |
// Composing final rebase file | |
return [] | |
.concat(dropOperations) | |
.concat(pickOperations) | |
.join('\n') | |
}, [amount]) | |
console.log(`Removed ${amount} commits starting ${anchor}`) | |
} | |
// Runs a git-rebase-interactive in a non interactive manner by providing a script | |
// which will handle things automatically | |
function gitRebaseInteractive(head, fn, args) { | |
execa.sync('git', ['rebase', '-i', head], { | |
env: { | |
GIT_SEQUENCE_EDITOR: gitEdit(fn, args) | |
} | |
}) | |
} | |
// Evaluates a script in a new process which should edit a git file. | |
// The input of the provided function should be the contents of the file and the output | |
// should be the new contents of the file | |
function gitEdit(fn, args) { | |
args = args.map(arg => `'${arg}'`).join(', ') | |
const body = fn.toString() | |
.replace(/\\/g, '\\\\') | |
.replace(/`/g, '\\`') | |
const scriptFile = tmp.fileSync({ unsafeCleanup: true }) | |
fs.writeFileSync(scriptFile.name, ` | |
const fs = require('fs') | |
const file = process.argv[process.argv.length - 1] | |
let content = fs.readFileSync(file).toString() | |
content = new Function(\`return (${body}).apply(this, arguments)\`)(content, ${args}) | |
fs.writeFileSync(file, content) | |
fs.unlinkSync('${scriptFile.name}') | |
`) | |
return `node ${scriptFile.name}` | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment