Skip to content

Instantly share code, notes, and snippets.

@DAB0mB
Last active September 3, 2018 10:06
Show Gist options
  • Save DAB0mB/51d2f1ae5f71e13733b9b476ad0d9f9c to your computer and use it in GitHub Desktop.
Save DAB0mB/51d2f1ae5f71e13733b9b476ad0d9f9c to your computer and use it in GitHub Desktop.
usage: $ ./git-remove.js <anchor> <amount>
#!/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