jj
jj copied to clipboard
FR: search for text in commit history
Is your feature request related to a problem? Please describe.
I want to find the commit in which I removed a line of code. With git, I could use git log -S foo, or git log -G foo (the difference is subtle and not interesting for my purposes). I don't see any equivalent in jj.
Describe the solution you'd like
Add a way to filter commits by their diff. I think this could fit in well as a revset function; maybe contents(foo), where foo is a string pattern? Then jj log --revisions would work without needing to add a new flag.
Describe alternatives you've considered
jj log -p and then searching in the pager, which works but is unnecessarily slow and shows more commits than the one i care about.
Additional context
; jj --version
jj 0.13.0-81b0e3bf3bf6f230740e93532b9a9767e8a4ef6e
I think this could fit in well as a revset function; maybe
contents(foo), wherefoois a string pattern?
hg calls it diffcontains(pattern). Implementing unoptimized version wouldn't be that hard.
We'll have to decide whether paths passed on the CLI should feed into the revset. That is, should jj log -r 'diffcontains(foo)' dir search for changes to "foo" only inside dir/ or also outside? We have a similar question with jj log -p dir, which currently filters both the log and the diff.
i would expect it to only search inside dir/, the same as git log -S foo dir. i think the alternative you're suggesting is "show commits that modify dir/ and also contain 'foo' anywhere in their diff"? i don't find that intuitive; in git the way i would do that is probably git rev-list -- dir | xargs -I{} git rev-list {} -- foo, but more likely i wouldn't try to do that at all.
oh, it turns out git has a --full-diff option to opt into that behavior. so that's another option available, limit both by default but only limit one if someone opts-in.
I also find it more intuitive to limit the matching revisions by default, and I should have said that to avoid confusion. The reason I mentioned it was mostly because revsets don't currently interact with paths passed outside of the revset. The filtering by path I mentioned earlier is done outside of the revset here: https://github.com/martinvonz/jj/blob/64fa84746a5fc398cc71d591024a5e3fe6aa70e7/cli/src/commands/log.rs#L82-L91
The difference is that for jj log -r 'diffcontains(foo)' dir would have to pass in the directory as context for the revset. We already do pass in some context (e.g. the current directory and the current workspace id) when parsing revset expressions, so it's not completely new.