In mercurial how can I find changesets that contain a string?
Asked Answered
I

2

15

Let's say I have the following revisions:

rev 1:
+ Dim Foo as integer

rev 2:
+ I like big butts, I cannot lie

rev 3
- Dim Foo as integer

Foo is in rev 1 & 2, and removed from three. What command can I issue that will return all changesets that Foo was added or deleted?

Ideally I'd like to be able to do this from toroisehg as well

Individual answered 15/3, 2012 at 18:26 Comment(2)
possible duplicate of Finding changesets in mercurial by grepping the patchPirn
Foo is content of file, filename or text in commit message?Psychotomimetic
P
23

You can use the grep command :

hg grep --all Foo

To address Lazy Badger concerns in comments.

$ hg init
$ echo "Dim Foo as integer" > test 
$ hg commit -m "1"
$ echo "I like big butts, I cannot lie" > test 
$ hg commit -m "2"
$ echo "Dim Foo as integer" > test 
$ hg commit -m "3"
$ hg grep --all Foo

The output of the grep command is :

test:2:+:Dim Foo as integer
test:1:-:Dim Foo as integer
test:0:+:Dim Foo as integer

Which means, Foo was first seen in the file test on revision 0 (the + sign tells us that), then it dissapeared on revision 1 (the - signs), and reappear again on revision 2.

I don't know if it is what you want, but it clearly indicates revision on which the searched word was added or deleted.

Pirn answered 15/3, 2012 at 19:19 Comment(5)
BTW: grep returns files, not changesets. OP asked "all changesets..."Psychotomimetic
@LazyBadger You can see that grep does exactly that, telling us on which revision the searched pattern appears and disappearsPirn
I would like changesets, but this does sort of get me there.Individual
how would one easily match revision to changeset?Rangefinder
@NickJ, you can output changeset hashes by using an output template like -T "{node}\n". I've posted an answer below.Katlaps
K
3

Use hg grep --diff PATTERN [FILE]... to search in diffs, and specify a template to print the changeset specifically.

This answer is no more than an update of @krtek's excellent answer. It contains a few examples more, and it uses the modern --diff flag rather than the --all flag, which was deprecated since krtek answered. Both flags do the same thing: instruct hg grep to search all diffs for the given pattern.

Here are three example invocations and outputs. (The script to create the example repository is at the end of this post.)

Ordinary grep

$ hg grep --diff Foo 
myfile:2:+:Dim Foo as integer
myfile:1:-:Dim Foo as integer
myfile:0:+:Dim Foo as integer

Use a template to extract commits' revision numbers and hashes

$ hg grep --diff Foo -T '{rev}:{node|short}\n'
2:2c425adcc0b1
1:5a46fef3be7c
0:b8d4a0cc48a5

See all available data/templating fields

$ hg grep --diff Foo -T json
[
 {
  "change": "+",
  "date": [1662367225, -7200],
  "lineno": 1,
  "node": "2c425adcc0b1fdcdea5ab8c0a864ce0af4a80478",
  "path": "myfile",
  "rev": 2,
  "texts": [{"matched": false, "text": "Dim "}, {"matched": true, "text": "Foo"}, {"matched": false, "text": " as integer"}],
  "user": "Lady MacBeth <[email protected]>"
 },
 // ...
]


Commands to set up the example repository, used in the examples above:

# Create the repository
hg init
touch myfile
hg add myfile

# Create 3 commits
echo "Dim Foo as integer" > myfile
hg commit -m "1"
echo "Tomorrow, and tomorrow, and tomorrow" > myfile
hg commit -m "2"
echo "Dim Foo as integer" > myfile
hg commit -m "3"
Katlaps answered 5/9, 2022 at 8:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.