Skip to content

Instantly share code, notes, and snippets.

@fabien0102
Last active January 16, 2017 08:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabien0102/c009b8e05103b59d57f40ebfa9764871 to your computer and use it in GitHub Desktop.
Save fabien0102/c009b8e05103b59d57f40ebfa9764871 to your computer and use it in GitHub Desktop.
Git log as a json
// Usage:
// 1. Paste this file into root directory
// 2. Exec `node gitlog.js > output.json` in a console
// 3. Do what you want with output.json \o/
const exec = require('child_process').exec;
// see https://git-scm.com/docs/pretty-formats for placeholder codes
const fields = {
refs: { value: '%d', parser: a => a.replace(/[\(\)]/g, '').replace('->', ',').split(', ').map(a => a.trim()).filter(a => a) },
commit: { value: '%H' },
commitAbbrev: { value: '%h' },
tree: { value: '%T' },
treeAbbrev: { value: '%t' },
parents: { value: '%P', parser: a => a.split(' ') },
parentsAbbrev: { value: '%p', parser: a => a.split(' ') },
'author.name': { value: '%an' },
'author.email': { value: '%ae' },
'author.timestamp': { value: '%at', parser: a => +a * 1000 },
'committer.name': { value: '%cn' },
'committer.email': { value: '%ce' },
'committer.timestamp': { value: '%ct', parser: a => +a * 1000 },
subject: { value: '%s' },
body: { value: '%b' },
notes: { value: '%N' }
};
const keys = Object.keys(fields);
exec(`git log --pretty=format:"%x01${keys.map(a => fields[a].value).join('%x00')}%x01" --numstat --date-order`, (err, stdout, stderr) => {
if (err) return console.error(`exec error: ${err}`);
const data = stdout.split('\u0001');
const stats = data.filter((a, i) => (i + 1) % 2);
let json = data.filter((a, i) => i % 2).map((raw, k) => {
return Object.assign(raw.split('\u0000').reduce((mem, field, j) => {
if (/\./.exec(keys[j])) {
let nameParts = keys[j].split('.');
mem[nameParts[0]] = Object.assign({}, mem[nameParts[0]], { [nameParts[1]]: fields[keys[j]].parser ? fields[keys[j]].parser(field) : field.trim() });
} else {
mem[keys[j]] = fields[keys[j]].parser ? fields[keys[j]].parser(field) : field.trim();
}
return mem;
}, {}), {
// Add parsed stats of each commit
stats: stats[k + 1].split('\n').filter(a => a).map(a => {
let b = a.split('\t');
return {
additions: +b[0], deletions: +b[1], file: b[2]
};
})
});
});
console.log(JSON.stringify(json));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment