jj icon indicating copy to clipboard operation
jj copied to clipboard

FR: search for text in commit history

Open jyn514 opened this issue 1 year ago • 5 comments

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

jyn514 avatar Feb 04 '24 00:02 jyn514

I think this could fit in well as a revset function; maybe contents(foo), where foo is a string pattern?

hg calls it diffcontains(pattern). Implementing unoptimized version wouldn't be that hard.

yuja avatar Feb 04 '24 02:02 yuja

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.

martinvonz avatar Feb 04 '24 17:02 martinvonz

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.

jyn514 avatar Feb 04 '24 18:02 jyn514

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.

jyn514 avatar Feb 04 '24 18:02 jyn514

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.

martinvonz avatar Feb 04 '24 18:02 martinvonz