git's pickaxe (git log -S) – an underrated git flag
2023-07-22
git log -S <search text> will bring up the commits that add or remove the search text. This searches the diff, not the commit message, and tracks across renames, making it easier than repeated git blame! Some uses include:
- find commits that that use a particular data structure
- grab the commit that introduced a particular error message
It has some variations:
git log -Gwill also show "modification" diffs (+1 -1) as opposed to changes that only add (+1) or remove (-1).- Adding
--pickaxe-regexenables regular expressions for-Gand-S. - Adding
--pickaxe-allwill show the entire commit, not just the changed files, useful with--stator--patch.
A mnemonic for this command is "use -S to search changes with a Specific String".
A git command alias might look like the following:
[alias]
pickaxe = git log --pickaxe-all --pickaxe-regex -GCommentary
I learned about this buried in the search options of git instaweb, which is a web frontend that comes with standard git installations1. The instaweb documentation describes it as the following:
All commits that caused the string to appear or disappear from any file (changes that added, removed or "modified" the string) will be listed.
In true git documentation style, the "pickaxe" concept isn't documented except for other flags that modify the behaviour of -S and -G, there are no equivalent long-form flags, and the documentation says [un]helpfully that this is "intended for the scripter's use." The git command-line interface is well-known for being unintuitive and inconsistent2, yet still useful, and this happens to be one of those instances.
More broadly, the command-line and other textual interfaces are high in configurability and extensibility, but low in discoverability: adding more functionality adds no interface overhead, but you need to know about the feature to use it. Autocompletion and command palettes are low-impact extensions to pure command-line interfaces that provide more affordance for discovering relevant commands. Alternatively, you could read through the man pages3, as recommended by Hillel Wayne in "Search Less, Browse More".
This feature was added to git early in its history, in 2005 (commit is here), and the "pickaxe" concept was copied from something called "JIT", which is mentioned several times in early git commits, but which I haven't looked into yet. As expected, the name is difficult to search for.
git instawebis sometimes useful to visually navigate the historical state of files when you're offline. If you happen to find yourself without a copy oflighttpd, you can trygit instaweb --httpd='python3 -m http.server', but don't forget to rungit instaweb --stopafterwards.↩︎This has been improved somewhat with the variety of new commands like
git restoreandgit switch, for which the man pages have the following warning:
↩︎THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
For example,
git-rev-parse(1)is a treasure trove of obscure knowledge about the git ref format. Heads up to Mark Dominus for bringing this to my attention.↩︎