3 ms·
Anyone got a (git-based) one liner to get this info for an arbitrary repo?
by thenoblesunfish 5y ago
Anyone got a (git-based) one liner to get this info for an arbitrary repo?
- valyagolev 5y agohere you go git rebase -i --exec 'ack TODO | wc -l >> log' HEAD~20 (create a temp branch first!, then substitute your starting revision, and save-quit the editor that'll pop up)
- unwind 5y agoAs a starting point, git log --format=format:"%at %H" | sort -nr gives a list, with the oldest entry first, of just "hash timestamp" pairs, one per line. You can then use e.g. date -I --date='@1620720025' to convert the timestamp back to a human-readable date in ISO format, i.e. "2021-05-11". The next step would be to loop over the list, checkout each revision, grep and wc the TODOs, and collect into date buckets. Anyone? :)
- pizza234 5y agoYou've asked for it ;) This prints the years - you can the group and plot them as you wish (it should be fairly easy, but I wrestled enough with git). It's a non-rigorous script (eg. it assumes nobody's email/name includes an `YYYY-MM-DD`-like string, and that filenames don't include the colon character): grep -P '\bTODO\b' -n -R -- * | awk -F: '{ system("git blame "$1" -L "$2","$2) }' | perl -lne 'print /(\d{4})-\d\d-\d\d/' The working is actually fairly simple: - grep prints filenames and lines - awk captures the filename and line, and executes a git blame on it - perl matches the year and prints it In the Perl matching expression, month and day are not strictly necessary, but disambiguate potential 4-digit numbers in the email/name. I'm very underwhelmed by the lack of customization of the `git blame` command - `--porcelain` is also uncustomizable, which makes things even uglier. Note that `git blame` also mishandles some edges (printing "fatal: file [...] has only 1 line").
- peff 5y agoWhat do you want `blame --porcelain` to do that it doesn't? Using: git blame --line-porcelain "$1" -L "$2,"$2" | perl -MPOSIX=strftime -lne '/^author-time (\d+)/ and print strftime("%Y", localtime($1))' I suppose it would be a little more convenient if you could ask `git blame` to format the whole line itself, but that wouldn't be part of the `--porcelain` output. All that said, that pipeline is quite slow on something like linux.git, as it runs a series of blames which will walk over the same history many times. I think: git log -STODO --format=%ad --date=short would be much faster (it's not _quite_ the same thing, as it counts TODOs which went away, but is a reasonable variant).
- pizza234 5y ago> What do you want `blame --porcelain` to do that it doesn't? Using: It increases the complexity, due to time conversion. One can certainly solve the general problem by throwing enough awk/perl/sed at it, but an option to customize the blame output would make it significantly more ergonomic (and the oneliner much simpler).
- cerved 5y agoI'll throw this into the mix git --no-pager grep -I --full-name --line-number 'TODO' |\ sed 's/\(^[^:]*\):\([0-9]\+\):.*/\1\n\2/' |\ xargs -d '\n' -n2 sh -c 'git --no-pager blame "$0" -L $1,$1' Not blazing fast but I think it does okay-ish. What it does: 1) git-grep for files that are checked in, not "binary" that contain the string 'TODO' 2) sed away the actual line contents (git-grep doesn't seem able to only output file:line-nr) 3) use xargs and sh to call git blame on that file:line-nr This shows the last time the TODO line was modified, ie: it may have been created 10 years ago but somebody modified the last yesterday edit: one might want to throw in --cached to git-grep to search the index and not just the current working-tree