I have a Mercurial repository with ~800 changesets and I need to find the first changeset where the word Example appeared. The word appears inside a .php file and not on a commit comment etc.
What is the quickest/easiest way to do that?
try hg grep Example *.php
hg grep [OPTION]... PATTERN [FILE]...
search for a pattern in specified files and revisions
Search revisions of files for a regular expression.
This command behaves differently than Unix grep. It only
accepts Python/Perl regexps. It searches repository
history, not the working directory. It always prints the
revision number in which a match appears.
By default, grep only prints output for the first
revision of a file in which it finds a match. To get it
to print every revision that contains a change in match
status ("-" for a match that becomes a non-match, or "+"
for a non-match that becomes a match), use the --all
flag.
options:
-0 --print0 end fields with NUL
--all print all revisions that match
-f --follow follow changeset history, or file
history across copies and renames
-i --ignore-case ignore case when matching
-l --files-with-matches print only filenames and revisions
that match
-n --line-number print matching line numbers
-r --rev search in given revision range
-u --user list the author (long with -v)
-d --date list the date (short with -q)
-I --include include names matching the given
patterns
-X --exclude exclude names matching the given
patterns
use "hg -v help grep" to show global options
The selected answer is incomplete:
hg grep --all --files-with-matches 'PATTERN' [FILES]
is normally what you want.
You would want to use the --diff (--all is deprecated) flag of hg grep. It searches the diffs rather than file contents itself, what this would result in is, you would get all the changesets/revisions where the word Example appeared or removed.
Now to get the first hit you need to pass this in revlog order via the -r flag. That is the revisions will be searched from 0 to tip. ( -r 0:tip )
And for the .php files you would want to pass -I flag which is for file name patterns.
So your command will be :
hg grep --all -r 0:tip "Example" -I "*.php"
hg help filesets
...
"grep(regex)"
File contains the given regular expression.
hg locate "set:grep(Example) and **.php"
or
hg locate "set:**.php and (**Example*)"
Related
I am trying to find a list of source files that have not been modified for the past few years.
This is one aspect I am trying to measure to try to help us understand the amount of stability and change in a given project over time.
Is there any way in mercurial to identify the files that have not been modified since a given revision?
There is some ambiguity in the question, but it can probably be answered using the status (st) command. For example, to obtain a listing based on a comparison of the files at revision R with those in the pwd, you could run:
hg st --rev R -cn
The -c option is equivalent to "--clean" (meaning in effect "no change").
To compare the files at revision R with those in the most recent commit:
hg st --rev R:-1 -cn
There are many ways to specify "R", e.g. 0 for the initial commit.
Posting my own answer.
I cloned the repository twice into new directories.
Then updated one to the current version and one to the original baseline revsion
hg update <rev>
Then used the diff command to find files that were identical (excluding whitespace changes)
diff -sqrbwB original current | grep "identical"
The diff flags are as follows:
-s reports identical files (facilitating the grep for "identical")
-q brief report (don't need a detailed report of differences)
-r recursively follow directories
-b ignore space changes
-w ignore all space
-B ignore Blank lines
Not sure if -b -w and -B are all necessary but it worked and output a list of files that have not chaged.
Say the string "abc123" first appeared in revision 12, and the current revision is 200. How can I know that the string "abc123" first appeared in revision 12? Plus, how do I get verision 12's hash?
You should be able to use
hg grep abc123 -r 0:tip
to search revisions in order for the first revision that the string abc123 appears in. Keep in mind that this can be a very slow process for a large repository with a long history, as each revision will have to be checked individually.
To speed up the process for such a repository, you can use hg bisect. E.g.:
hg bisect -r # reset bisect if needed
hg bisect -g 0
hg bisect -b tip
hg bisect -c '! hg grep -r . abc123'
Note that marking revisions that contain the string as "bad" and those that don't contain it as "good" seems counterintuitive, because bisect is normally used to hunt for the first revision that contains a bug. Thus the "bad" revisions are the ones that contain the string.
Note also that bisect may not work if there are revision ranges that do not contain the string you are looking for.
Finally, the ! operator to negate a shell exit code may not be supported by some shells. In those cases, use
hg bisect -c 'if hg grep -r . abc123; then false; else true; fi'
instead.
To get the hash of (say) revision 12, use:
hg id -i -r 12
or:
hg id --debug -i -r 12
The latter version will print the full hash, the former will give you the abbreviated hash.
Mercurial 1.7.5 on Windows.
I have a few files I have modified, and want to split them into two commits. To do so, I'm playing with the -I (or --include) option. Docs state:
-I --include PATTERN [+] include names matching the given patterns
I haven't been able to figure out how to include more than one pattern yet. I've tried:
hg status -I C:\folderToSolution\Project1\**.cs C:\folderToSolution\Project3\**.cs
hg status -I C:\folderToSolution\Project1\**.cs +C:\folderToSolution\Project3\**.cs
(Using status to test my pattern before committing.)
What's the syntax for getting more than one pattern in the option?
Specify -I before each pattern
hg status -I C:\folderToSolution\Project1\**.cs -I C:\folderToSolution\Project3\**.cs
The [+] in the documentation means that the option can be specified more than once.
I have a couple branches that I need to merge, but I don't know where some of the changes are coming from that are showing up in my merge tool. The change sets of local and other are obvious, but how can I find out which change set the base file came from? I'm working in a repository with dozens of branches, so viewing the graph and tracking it doesn't work very well.
Using revsets (Mercurial 1.6 and later), you can get the common ancestor of two changesets with:
hg log -r ancestor(rev1,rev2)
Try the hg grep command:
hg grep [OPTION]... PATTERN [FILE]...
search for a pattern in specified files and revisions
Search revisions of files for a regular expression.
This command behaves differently than Unix grep. It only accepts
Python/Perl regexps. It searches repository history, not the working
directory. It always prints the revision number in which a match appears.
By default, grep only prints output for the first revision of a file in
which it finds a match. To get it to print every revision that contains a
change in match status ("-" for a match that becomes a non-match, or "+"
for a non-match that becomes a match), use the --all flag.
Returns 0 if a match is found, 1 otherwise.
options:
-0 --print0 end fields with NUL
--all print all revisions that match
-f --follow follow changeset history, or file history across
copies and renames
-i --ignore-case ignore case when matching
-l --files-with-matches print only filenames and revisions that match
-n --line-number print matching line numbers
-r --rev REV [+] only search files changed within revision range
-u --user list the author (long with -v)
-d --date list the date (short with -q)
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
--mq operate on patch repository
[+] marked option can be specified multiple times
use "hg -v help grep" to show global options
You can use it like:
hg grep "a string"
and it will tell you in which revision it was first added.
If you're looking for something less search-y and more overview-y you can use hg log -v to see what files were changes in each changeset and hg log -p to see the actual diffs for each.
I am using mercurial for version control of a few files in a directory. Suppose I have 10 commits (10 changesets or revisions). I want to just view how a particular file, say thisFile.py, looked in its 7th revision. I don't want to revert back to this older version. I don't want to go and make any changes or fix any bugs in this previous version. I simply want to see it, without affecting the latest version of the file or the mercurial history in any way. Is there a simple way to do it?
Use the hg cat command with the -r (revision) argument.
hg cat path_to/myfile.cpp -r 46
where 46 is the revision number (use hg log to see revision history)
hg cat [OPTION]... FILE...
Print the specified files as they were at the given revision.
If no revision is given, the parent of the working directory is used,
or tip if no revision is checked out.
Output may be to a file, in which case the name of the file is given
using a format string. The formatting rules are the same as for the
export command, with the following additions:
%s: basename of file being printed
%d: dirname of file being printed, or '.' if in repository root
%p: root-relative path name of file being printed
Returns 0 on success.
options:
-o, --output print output to file with formatted name
-r, --rev print the given revision
--decode apply any matching decode filter
-I, --include include names matching the given patterns
-X, --exclude exclude names matching the given patterns
To extract a specific revision of a specific file you can do this in Windows:
hg cat "<FileToBeExtractedPath>" -r 9 > "<ExtractionPath>"
Here, 9 is the revision number.
Or even better:
hg cat "<FileToBeExtractedPath>" -r 9 -o "<ExtractionPath>"