Mercurial: extdiff makes an unnecessary snapshot of the working directory? - mercurial

Here's what I have in my Mercurial.ini ...
[extdiff]
cmd.bcomp = C:\Program Files\Beyond Compare 3\BCompare.exe
opts.bcomp = /leftreadonly
So, the extdiff extension is working fine except that even when one side of the comparison is my working directory, as in the case where I only give one revision argument, e.g. hg bcomp -r 25 to get a diff between rev25 and the working directory, it causes my diff tool, in this case BC3, to open up a folder comparison session comparing a snapshot of rev25 to a snapshot of the working directory, such as...
left: C:\Windows\Temp\extdiff.v20d13s\MyCode\
right: C:\Windows\Temp\extdiff.q78g269\MyCode\
Is there a way for me to tell it to diff against the actual live working directory on the right side so I can edit from inside the diff tool? This seems to work just fine through SVN's external diff functionality. I realize it will display a lot of orphans on the right --I'll be glad to suffer through having to filter those out.

I've never found a way to prevent extdiff from copying the changed files to the Temp directory, but if your diff tool allows in-place edits then Mercurial will copy the changed files back to the working directory when you exit the tool.
For example, using Beyond Compare, this is the relevant piece from my Mercurial.ini:
[extdiff]
cmd.bcomp = C:\Program Files\Beyond Compare 3\BCompare.exe
opts.bcomp =/expandall /solo /lro

extdiff only copies divergent files between the two changesets to the temp dir, so that the diff tool will not show identical files. It'd be nice if it could detect that one version is working copy and just pass the working directory, and any decent diff tool should allow you to ignore identical files.
That's why if you do hg bcomp <file1> -r<rev> you'll indeed see the working copy because there's only one file to diff.
#Niall C's answer is great, but if you're not comfortable with changing temp files, or your diff tool isn't as cool as bcomp, it shouldn't be hard to write a little extension to copy the files from the non-working copy changeset to a temp dir just like extdiff does, then invoke diff tool between the temp dir and your working dir.

I'm NOT an expert at Mercurial, but I'm having some problems with extdiff as well, and I MAY have inadvertetly found the answer to your question while trying to figure out mine. I may also be completely wrong. ;-)
Anyway, it looks to me like if you explicitly provide a version number to compare against, extdiff takes a snapshot of both versions you're trying to compare (even though you didn't specify BOTH sides of the DIFF; the unspecified side is implicitly the working directory).
The only way I've been able to get extdiff to simply work off of the working directory is to not specify a version to compare to (I guess doing this works off of the tip?).
Sorry I'm not terribly helpful. Hope you find your answer!

Related

Find likely base revision in a mercurial repository

I received some code as a tar archive (without the .hg directory). I know which repository this code is based on, but not which revision was used as a base for these modifications. Is there some way to find this out by just looking at the files? This is similar to Given a file, how to find out which revision in a mercurial repository this is? but I cannot reach the author of the code, so I cannot control how the files are extracted from the repository. I am also dealing with modified files here so the diff to the base revision would not be empty.
My fall-back plan would be to loop through all revisions and using the one with the smallest diff, but I'm still hoping there is a better solution.
There's no automated way to do it, but you could possibly reduce the time by using a hg bisect --command diff ... command to zero in on it.
As a tip if you (I know it probably wasn't) you ever has to give someone a snapshot again, use hg archive to make it. It includes a .hg_archive.txt file with version info that'll help if you have to do this again.

Mercurial - Look into history of file without updating

I'm working in this file and I come across a piece of code which I think has changed at some point in history, and I would like to know where it changed.
It's a pretty big file with a lot of history, so when I use hg diff, I get a enormous list and I don't think it's efficient to search through that.
It would be really neat if I can look into an old revision of the file, to see what the file looked like at a certain point in time. Then I can see how the code worked back then so I can conclude how the bug evolved. Of course, I want to do this without updating the file, because I'm currently working in it and have made changes in it.
So, is there any way you can look into the history of a file without updating it?
There are a few tools to help you:
To get the history of a file you can just use hg log FILE which is probably the best starting point.
You can also use hg annotate FILE which lists every line in the file and says which revision changed it to be like it currently is. It can also take a revision using the --rev REV command tail to look at older versions of the file.
To just list the contents of a file at a given revision you can use hg cat FILE --rev REV.
If it proves too hard to track down the bug using those tools, you can just clone your repository somewhere else and use hg bisect to track it down.
hg bisect lets you find the changeset that intoduced a problem. To start the search run the hg bisect --reset command. It is well document in Mercurial: The Definitive Guide.

How resolve this Mercurial conflict?

I'm frustrated with Mercurial and Python since it makes easy things difficult. I have a trivial conflict and since Mercurial does not give any suggestion what to do I don't know even how to resolve this trivial file conflict:
The conflict is trivial but if I can't resolve this I can't resolve anything complicated either. Can I just edit the file to a way I want and commit it again from anywhere? Should I run hg merge? Why can't Mercurial even let me choose a version to keep? Why is something trivial near impossible to do without digging through 1000 poorly written manpages?
You need to look at the KDiff3 documentation, in particular the section on merging and the output window. To resolve the conflict, you need to decide if live or january is the right choice for the line. That decision is yours to make, no tool can know if you meant one or the other.
In KDiff3, you press Ctrl + 2 to select live, press Ctrl + 3 to select january or right-click in the margin of the bottom window and select the line you want. You can also click in the bottom window and edit the line manually.
Mercurial let's you configure your merge tool any way you like. TortoiseHg ships with a default configuration that puts KDiff3 in the top of the list, but you can use another tool if you like. A merge tool is really just a program that accepts four filenames: the three files to compare (base, parent 1, parent 2) and an output file name.
To resolve conflicts on the command-line you need to launch a suitable command-line three-way merge tool. You can for example merge with vim if you like. (I'm afraid I don't know anything about vimdiff, I use KDiff3 myself.)
If you don't like to see merge tools pop up, then you can set
[ui]
merge = internal:merge
to make Mercurial use the internal three-way merger only. It will merge files fine when the edits are not in conflicts. When there is a conflict, the file is marked as "unresolved" and conflict markers are stored in the file.
You then need to edit the file by hand to get the version you want. You can also re-merge and pick either the local (your) version:
$ hg resolve --tool internal:local your-file
or the other version:
$ hg resolve --tool internal:other your-file
You restart the merge completely with hg resolve your-file. The file needs to be marked "resolved" before you can commit it. This is done with hg resolve --mark your-file. See hg resolve --list for the status of the current merge.
Base is the previous version in your local system,
Parent 1 is your current changes,
parent 2 is the file from server.
If you need your changes need to be checked in, select B everywhere in the merge menu.
If you want the latest server version in your local machine, select C everywhere in the merge menu

How to let mercurial external diff tool deal with file rename?

If I commit a file rename and use extdiff to see the diff in Beyond Compare or kdiff3, they show two different files on each side.
With Beyond Compare I can manually pick arbitrary files from each side to compare, but it's a huge pain if I have many renames (i.e. changing a java package name for refactoring).
I understand why it's so: extdiff simply makes two temp snapshot directories for the diff tool.
So my question is: is there any way to convey the rename to the diff tool, such that it will compare the old file name with the new file name?
This is probably specific for each diff tool. So if you know a tool that supports it, please, please let me know.
Note This only works for diffs with TortoiseHg.
The way I've configured my Mercurial installation, with Beyond Compare 3, is as follows:
(note, these are only the options relevant to diff and merging, you still need other options in some of the same sections, so only add or change, don't clear out your old sections and replace with the ones below)
[ui]
merge = bc3m
[extensions]
extdiff=
[extdiff]
cmd.bc3d = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe
opts.bc3d = /lro
[merge-tools]
bc3m.executable = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe
bc3m.args = $local $other $base $output /automerge /reviewconflicts /closescript /lro /rro /title1="Left parent" /title2="Right parent" /title3="Common base" /title4="Merged output"
bc3m.priority = 1
bc3m.premerge = True
bc3m.gui = True
[tortoisehg]
vdiff=bc3d
This now:
Auto-merges if possible, not showing a merge-GUI unless there's a merge conflict
Diff for a renamed file shows the old filename on the left side and the new one on the right side (funky temporary directory names though)
Important note: Do not use the same name for the merge tool and the diff tool (like bc3 for both). It confuses the tools involved and diffs just punt to the startup screen of BC. That's why the merge tool is named bc3m and the diff tool is named bc3d.
Also note that I've dropped using the built-in beyondcompare tools, as they seem incorrectly configured. In particular, the auto-merge part did not happen when using the built-in tool, but now works nicely. Also, with the built-in tool, visualizing diffs with renames showed the directory comparison or just punted to the startup screen of BC which makes you pick the type of comparison you want.
So in the end I just experimented until I found the right options and set everything up myself.
Handling renames requires a digging into history which a typical scm has. Specially dvcs like Mercurial. That is how, they can handle renames.
Some thing of interest could be the fact that Git doesn't track renames, operates on content and renames don't matter.
Diff tool can handle examining changes but it can tell nothing about the files within it. It will also be erroneous with a preceding history to tell if the file has been renamed or not. Any external diff tool usually examines contents and hence the task of supplying the files will remain with the user.
How ever, Mercurial does track renames. See this extentsion that can be used to track renamed files. You can use that to supply any external diff tool the right filenames to compare.

suggestions for using PATH to executables with version control (Mercurial)

So I'm pretty new to version control but I'm trying to use Mercurial on my Mac to keep a large Python data analysis program organized. I typically clone my main repository, tweak the clone's code a bit, and run the code on my data. If the changes were successful I commit and eventually push the changes back to my main repository. I guess that's a pretty typical workflow under version control.
My problem is that my code is run on the command-line, with several command-line arguments that refer to data files in the current working directory (and I have many such directories I need to test the code in, and they're outside of version control). So before using Mercurial I just kept my code in one ~/bin directory which was part of my PATH environment variable. Now, with version control, I need to either (1) after each edit, copy my current clone's executables to the ~/bin directory before running the code on the command line, or (2) each time I clone my code, add my current clone's path to the PATH, or (3) specify the entire/path/to/my/programs on the command line each time I run the code. None of these are very convenient, and I'm left feeling like there must be an elegant solution that I just don't know. Maybe something involving Mercurial's hooks? I want my under-revision code to be runnable on the command line between commits, so this seemed to rule out hooks, but I don't know... Many thanks for any suggestions!
Ry4an's answer is good if you want to continue with the multiple-clones workflow. But it's also worth being aware that Mercurial's powerful enough to allow you most of the benefits of that workflow without ever leaving your single "main" repo. I.e. you can create branches (named or anonymous) for experimental features, easily "hg update" to whatever version of the code you want to test, even use the mq extension to prune branches that didn't work out.
What I do in such a case is set up a two deep chain of symlinks to my binary in my current clone. For example I'll have:
/usr/bin/myappname
which is a symlink to
/home/me/repos/CURRENT/bin/myappname
where /home/me/repos/CURRENT is a symlink to whatever my current working clone is, for example:
/home/me/repos/myproject-expirment
After setting up the initial /usr/bin/myappname symlink all I have to do is update the CURRENT symlink when I create a new clone on which I'm working.