TortoiseHg: Don't display ancestors in keyword search results - mercurial

I want to search my Mercurial repository for commits with a certain log message (e.g. "merge") using TortoiseHg.
This is my repository without any search:
And when I search for "merge" I get this:
So it seems like the search finds the first match and displays all of its ancestors. Filtering of non-matched change-sets it turned on:
I only want to see the matching ancestors. It works for a colleague of mine, but we couldn't find what's different between our environments. We both use version 3.9 on Windows 10 x64 with the same extensions.
Here's another example searching for "works!":
And using keyword specifically:
And filtering by author:
It just always finds the first match and displays all the ancestors...

So it seems like the search finds the first match and displays all of its ancestors
No, you miss here. Plain-text pattern TEXT in search means (internally) using predicate keyword() in revset, hg log -T {rev}^M -r keyword('merge') in your case. But:
"keyword(string)"
Search commit message, user name, and names of changed files for
string. The match is case-insensitive.
Search is wider, than you expect. Just compare with my repo, there "merge" is only part of log-message: only two direct relatives appeared in revset, because they both met condition
For "merge" only in log matching() may be better, but if you really want mergesets merge() is The Natural Way (tm), and final revset for mergests and it's parents may be
merge() or parents(merge())

I uninstalled TortoiseHg, deleted all of its files from the machine (AppData, configurations, etc.) and reinstalled from scratch and now it seems to work. Since I already tried reinstalling a month ago I guess that cleaning all the files helped.

Related

Given a file, how to find out which revision in a mercurial repository this is?

Assume that there is a file under hg version control. I have a particular version of that file, and I would like to find out in which revision this file was in this version.
I suspect that there are two possible ways to do this.
Do hg update in a loop and diff the file against subsequent versions (sloooow, but should work).
Make Mercurial put the rev number in a, say, comment in the second line of the file right before committing. From what I have read, a precommit hook might be of use. Then I don't have to compare anything, just look at the file itself (I'm assuming no-one will change this, of course, but this is rather safe assumption in my case).
My use case is a joint paper, written in LaTeX, with two coauthors who have no idea about version control at all, but I prefer to use it (for obvious reasons). We communicate by email, and there's effectively a human-based lock system ("I will not work on this file until you send me the next version, ok?"). The only problem that arises is that I'm sending version X to author B to proofread, then author C sends me a corrected version Y and I commit it into my repo, then author B sends his corrections Z (to version X) and I'm starting to get lost-but I can check the attachment in the email sent to B, and I only need to find out which revision it is.
So, my question is: which of the two ideas above would be better, or maybe there's yet another one to help me deal with this mess?
hg archive is good method for future work, but I can suggest at least 3 alternative work-styles and 1 fix for find-correct-version with updates
Future work
You can use separate named branches for co-authors and default for merged results, send co-author always head from his branch, update his branch after getting corrections (you'll always know, that you sent) and merge branches to default
One branch, revision-of-coworker marked with bookmark, which you later move to next point
Mercurial keywords considered somehow as a "feature of last resort", but in your case it's obvious and usable solution: just add keyword with hash-id in file (defaul extension instead of hook - easier and more reliable)
Current state
For finding changeset with source of file, you can try to use bisect (example) and test in test-script, f.e, CRC of file (you have needed CRC of unversioned file, check versioned file across history)
If you're happy to rely on finding the emails you send the reviewers, why not just include the revision hashes in them along with the files?
You can get this for almost zero extra effort by generating your attachment using hg archive, which will create a file containing 1) your files for review, and 2) .hg_archival.txt, complete with revision hash.
Though I'd be surprised if there isn't a more elegant way, even if your collaborators are dead-set against using version control.

How to embed version information in source code with Mercurial

I would like to embed some version information on top of my source code file with information such as version number, author, and date of edit.
Is there a simple way to do this with Mercurial?
This has been asked a lot here on Stackoverflow and the short answer is: you shouldn't do it.
You don't want a file that changes with every commit it makes merging a nightmare.
Better options are:
write the version string to a file on update
have you build/deploy script run $(hg id) and put that into the build at that time
Trust me, revision strings in files is CVS/SVN thinking. It has no place in a git / Mercurial world.
As comments and other answers mention, it is not a good idea to rely on CVS-like, automatically expanded, tags. Specially since you can extract whatever meta-information you need at any time and almost any granularity afterwards.
However, if you really need it (because your boss says so, for instance), the closest you can get is by making use of the keyword extension that comes bundled with mercurial.
My favorite way is to use the hgversioninfo plugin.
It generates a version.py file on the fly on "hg commit", "hg update", etc.
Yes it is possible, but you need to enable it. What you are asking for is basically the keyword extension. Be careful when enabling this the first time (read the section about kwshrink, kwexpand), because you wouldn't want the actual expanded keywords to become part of the revision history.

Have Mercurial use a custom merge tool for its own merges

Mercurial docs about what mercurial does when it has to do a 3way merge:
By default, Mercurial will attempt to do a classic 3-way merge on text
files internally before trying to use an external tool.
When it invokes the external tool, that is always a "manual merge".
Not all merge tools are created equally, and as it turns out my merge tool of choice (Araxis Merge), is often able to do an automatic merge of 3 files, where mercurial's internal merge tool was not able to do so.
This leads to the scenario of big merges where maybe a bunch of files merge cleanly, done by hg's internal mergetool, and then some other files do not merge cleanly but could have if hg would let me specify its mergetool. I find this to make big merges very inefficient, as you need to context switch a lot: hg pops up my merge tool, I think "oh darn, conflict", to then realize "oh wait, theres no conflict at all"
I wonder if I'm missing something here, or if there is really no way to make hg able to use a custom merge tool for its automatic attempts at doing merges.
I think you're looking for a switch to make Araxis Merge close itself automatically if it can auto-merge. I looked at the command line reference and their SCM integration document, but I'm actually not sure what switch it would be. You'll have to experiment yourself.
From Mercurial's point of view there is no such thing as a "manual merge". Mercurial tries to merge internally first (the so-called "premerge" step) and if that fails it looks for an external tool. The merge can still be fully automatic if that tool exists with an exit code of zero (successful exit). Mercurial will then consider the merge successful and go on to the next file. Depending on the tool, you wont notice this at all: Mercurial just runs the tool in the background and you're only prompted for action when there is a serious merge conflict.
You can use a custom merge tool with Mercurial. help merge-tools shows the order in which tools are chosen to run:
1. If a tool has been specified with the --tool option to merge or
resolve, it is used. If it is the name of a tool in the merge-tools
configuration, its configuration is used. Otherwise the specified tool
must be executable by the shell.
2. If the "HGMERGE" environment variable is present, its value is used and
must be executable by the shell.
3. If the filename of the file to be merged matches any of the patterns in
the merge-patterns configuration section, the first usable merge tool
corresponding to a matching pattern is used. Here, binary capabilities
of the merge tool are not considered.
4. If ui.merge is set it will be considered next. If the value is not the
name of a configured tool, the specified value is used and must be
executable by the shell. Otherwise the named tool is used if it is
usable.
5. If any usable merge tools are present in the merge-tools configuration
section, the one with the highest priority is used.
6. If a program named "hgmerge" can be found on the system, it is used -
but it will by default not be used for symlinks and binary files.
7. If the file to be merged is not binary and is not a symlink, then
"internal:merge" is used.
8. The merge of the file fails and must be resolved before commit.
More information can be found in help config - look for merge-tools and merge-patterns

A mercurial merge chose the wrong changes, what is the correct way to fix this?

Changes were made to our .vcproj to fix an issue on the build machine (changeset 1700). Later, a developer merged his changes (changes 1710 through 1715) into the trunk, but the mercurial auto-merge overwrote the changes from 1700. I assume this happened because he chose the wrong branch as the "parent" of the merge (see part 2 of the question).
1) What is the "correct" mercurial way to fix this issue, considering out of all the merged files, only one file was merged incorrectly, and
2) what should the developer have done differently in order to make sure this didn't occur? Are there ways we can enforce the "correct" way?
Edit: I probably wasn't clear enough on what happened. Developer A modified a line in our .vcproj file that removed an option for the compiler. His check-in became changeset 1700. Developer B, working from a previous parent (let's say changeset 1690), made some changes to completely different parts of the project, but he did touch the .vcproj file (just not anywhere near the changes made by Developer A). When Developer B merged his changes (becoming changes 1710 through 1715), the merge process overwrote the changes from 1700.
To fix this, I just re-modified the .vcproj file to include the change again, and checked it in. I just wanted to know why Mercurial thought that it shouldn't keep the changes in 1700, and whether or not there was an "official" way to fix this.
Edit the second: Developer B swears up and down that Mercurial merged the .vcproj file without prompting him for conflict resolution, but it is of course possible that he's just misremembering, in which case this whole exercise is academic.
I will address the 2nd part of you question first...
If there is a conflict, the automated merge tools should force the programmer to decide how the merge happens. But the general assumption is that a conflict will involve two edits to the same set of lines. If somehow a conflict arises because of edits to lines that are not close to each other the automated merge will blithely choose both of the edits and a bug will appear.
The general case of a merge tool always merging properly is very hard to solve, and really can't be with current technology. Here is an example of what I mean from C:
int i; // Someone replaces this with 'short i' in one changeset stating
// that a short is more efficient.
// ... lots of code;
// Someone else replaces all the 65000s with 100000s in another changeset,
// saying that more precision is needed.
for (i = 0; i < 65000; ++i) {
integral_approximation_piece(start + i/65000.0, end + (i + 1) / 65000.0);
}
No merge tool is going to catch this kind of conflict. The tool would have to actually compile the code to see that those two parts of the code have anything to do with eachother, and while that would likely be enough in this case, I can construct an example that would require the code to be run and the results examined to catch the conflict.
This means that what you really ought to do is rigorously test your code after a merge, just like you should after any other change. The vast majority of merges will result in obvious conflicts that a developer will have to resolve (even though that resolution is often fairly obvious), or will merge cleanly. But the very few merges that don't fit either category can't easily be handled in an automated fashion.
This can also be fixed by development practices that encourage locality. For example a coding standard that states "Variables should be declared near where they're used.".
I'm guessing that .vcproj files are particularly prone to this problem since they are not well understood by developers and so if conflicts do appear they will not be sure what to do with them. My guess is that this happened and your developer simply did a revert back to the revision (s)he checked in.
As for part 1...
What to do in this case depends a lot on your development process. You can either strip the merge changeset out and redo it, though that won't work very well if lots of people have already pulled it, and it will work especially poorly if there are lots of changesets that have already been checked in that are based on the merge changeset.
You can also check in a new change that fixes the problem with the merge.
Those are basically your two options.
The tone of your post seems to me to indicate that you may have some politics surrounding this issue in your organization, and people are blaming this error on the frequent merges of Mercurial. So I will point out that any change control system can have this problem. In the case of Subversion, for example, every time a developer does an update while they have outstanding changes in their working directory, they are doing a merge, and this kind of problem can arise with any merge.
In mercurial a merge doesn't have a single parent, it by definition has two and only two parents. When someone is merging they're making two choices:
What two changesets will constitute the two changes
Which of those changesets will be the left-parent and which will be the right-parent
Of those two questions the first is very important, and the second barely matters at all, though it took me a while to come to understand that.
You select the left-parent by using hg update X. That changes the output of hg parents (or in newer versions hg summary) and essentially determines what's in your working directory before the merge.
You select the right-parent by using hg merge Y. That says merge X (the working directory's parent) with changeset Y. As a special case, if there are only two heads in your repository and your parent is already one of them then Y will default to the the other.
I'd have to see your resulting graph to know just what the developer did, but it's possible he didn't update to one head or another before invoking merge, which would have him merging one head with some point back in history.
If your developer picked the right parents for the merge then the left vs. right doesn't much matter -- the only real difference is that when one uses hg diff or hg log -p or some other command that shows the patch for a merge changeset, it's displayed relative to the left-parent. That's, however, mostly a factor in display only. Functionally they're pretty much identical.
Assuming your developer picked the right changesets then what he should have done was test the result of the merge before committing it. Merging is software development, not an annoying VCS side effect, and not testing before committing is the error.
Fixing
To fix this, just re-do the merge correctly. Use hg update to set one parent, use hg merge to pick the other. Make sure your current working directory is correct and then commit. You can get rid of his bad merge using something like hg strip or better, just close down his branch with hg commit --close-branch after updating to it.
Avoiding
You say "mercurial auto-merge", but mercurial doesn't really auto-merge. It does a premerge which is an extremely cautious combination of obvious changes, but it's so careful it won't even merge for you if each merge parent adds code in the same region because it can't know which block of code you'd rather have first.
You can disable this premerge entirely or on a file-by-file basis using the merge tool configuration options:
https://www.mercurial-scm.org/wiki/MergeToolConfiguration?highlight=premerge

How good is my method of embedding version numbers into my application using Mercurial hooks?

This is not quite a specifc question, and more me like for a criticism of my current approach.
I would like to include the program version number in the program I am developing. This is not a commercial product, but a research application so it is important to know which version generated the results.
My method works as follows:
There is a "pre-commit" hook in my .hg/hgrc file link to version_gen.sh
version_gen.sh consists solely of:
hg parent --template "r{rev}_{date|shortdate}" > version.num
In the makefile, the line version="%__VERSION__% in the main script is replaced with the content of the version.num file.
Are there better ways of doing this? The only real short coming I can see is that if you only commit a specfic file, version.num will be updated, but it won't be commited, and if I tried to add always committing that file, that would result in an infite loop (unless I created some temp file to indicate I was already in a commit, but that seems ugly...).
The problem
As you've identified, you've really created a Catch-22 situation here.
You can't really put meaningful information in the version.num file until the changes are committed and because you are storing version.num in the repository, you can't commit changes to the repository until you have populated the version.num file.
My solution
What I would suggest is:
Get rid of the "pre-commit" hook and hg forget the version.num file.
Add version.num to your .hgignore file.
Adjust version_gen.sh to consist of:
hg parent --template "r{node|short}_{date|shortdate}" > version.num
In the makefile, make sure version_gen.sh is run before version.num is used to set the version parameter.
My reasons
As #Ry4an suggests, getting the build system to insert revision information into the software at build time, using information from the Version Control System is a much better option. The only problem with this is if you try to compile the code from an hg archive of the repository, where the build system cannot extract the relevant information.
I would be inclined to discourage this however - in my own build system, the build failed if revision information couldn't be extracted.
Also, as #Kai Inkinen suggests, using the revision number is not portable. Rev 21 on one machine might be rev 22 on another. While this may not be a problem right now, it could be in the future, if you start colaborating with other people.
Finally, I explain my reasons for not liking the Keyword extension in a question of mine, which touches on similar issues to your own question:
I looked at Mercurials Keyword extension, since it seemed like the obvious solution. However the more I looked at it and read peoples opinions, the more that I came to the conclusion that it wasn't the right thing to do.
I also remember the problems that keyword substitution has caused me in projects at previous companies. ...
Also, I don't particularly want to have to enable Mercurial extensions to get the build to complete. I want the solution to be self contained, so that it isn't easy for the application to be accidentally compiled without the embedded version information just because an extension isn't enabled or the right helper software hasn't been installed.
Then in comments to an answer which suggested using the keyword extension anyway:
... I rejected using the keyword extension as it would be too easy to end up with the string "$Id$" being compiled into the executable. If keyword expansion was built into mercurial rather than an extension, and on by default, I might consider it, but as it stands it just wouldn't be reliable. – Mark Booth
A don't think that there can be a more reliable solution. What if someone accidentally damages .hg or builds not from a clone but from an archive? – Mr.Cat
#Mr.Cat - I don't think there can be a less reliable solution than the keywords extension. Anywhere you haven't explicitly enabled the extension (or someone has disabled it) then you get the literal string "$ID$" compiled into the object file without complaint. If mercurial or the repo is damaged (not sure which you meant) you need to fix that first anyway. As for hg archive, my original solution fails to compile if you try to build it from an archive! That is precisely what I want. I don't want any source to be compiled into our apps without it source being under revision control! – Mark Booth
What you are trying to do is called Keyword Expansion, which is not supported in Mercurial core.
You can integrate that expansion in make file, or (simpler) with the Keyword extension.
This extension allows the expansion of RCS/CVS-like and user defined keys in text files tracked by Mercurial.
Expansion takes place in the working directory or/and when creating a distribution using "hg archive"
That you use a pre-commit hook is what's concerning. You shouldn't be putting the rest of version_gen.sh into the source files thesemves, just into the build/release artifacts which you can do more accurately with an 'update' hook.
You don't want the Makefile to actually change in the repo with each commit, that just makes merges hell. You want to insert the version after checking out the files in advance of a build, which is is what an update hook does.
In distributed systems like Mercurial, the actual "version number" does not necessarily mean the same thing in every environment. Even if this is a single person project, and you are really careful with having only your central repo, you would still probably want to use the sha1-sum instead, since that is truly unique for the given repository state. The sha1 can be fetched through the template {node}
As a suggestion, I think that a better workflow would be to use tags instead, which btw are also local to your repository until you push them upstream. Don't write your number into a file, but instead tag your release code with a meaningful tag like
RELEASE_2
or
RELEASE_2010-04-01
or maybe script this and use the template to create the tag?
You can then add the tag to your non-versioned (in .hgignore) version.num file to be added into the build. This way you can give meaningful names to the releases and you tie the release to the unique identifier.