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

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.

Related

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

hg automatic merges with diff3

Consider a Hg project with two central branches/clones - e.g. DEV and PRD. When someone pushes a hotfix to PRD, an automated script on the central server goes to DEV and pulls the new changes. It then tries to merge the hotfix into DEV.
The problem is that the merge tool integrated into Hg is terrible - as soon as there are parallel changes to the same file it will fail. Take the following example:
parent:3,7c
four
five
six
seven
child1:3,7c
four
five5
six6
seven7
child2:3,7c
fourmore
five
six
more
seven
As you can see, there are no actual conflicts here. If we do the merge locally with kdiff, it solves this simple case without user input!
I'd like a way to get the central server to manage these cases. I thought of using kdiff3 in silent mode, but I can't install kdiff3 on it (it's a CLI only system that we don't even have admin access to), but maybe there is a way to plug diff3 into hg merge so it can resolve simple cases like this? I tried setting "[ui] /n merge = diff3" in the hgrc, but it just spits out the three versions to stdout. Am i missing some additional configuration? Or is there an easier/better tool?
Thanks a lot
To use diff3 as your merge tool, you need to add
[merge-tools]
diff3.args = $local $base $other -m > $output
to your configuration file. You can set the priority if needed, see the wiki. You'll also find more complicated recipes for using diff3 there.
However, I tested how diff3 treats your scenario with edits on adjacent lines, and just like Mercurial, it also refused to merge this cleanly. Different merge tools have different thresholds for what they consider a "conflict" and it seems that KDiff3 is more forgiving than Mercurial and diff3.
I suggest that you let the developer who makes the hotfix on PRD be responsible for merging it into DEV locally where he has access to tools like KDiff3. Automated merging on a server is generally considered to be bad — merges should be verified just a little by a human before you commit them. It's not much extra work after having made the hotfix.

How to store my binary assets with Mercurial?

I'm starting a game development project and my team and I will be using Mercurial for version control and I was wondering what a more appropriate way to store the binary assets for the game would be. Basically, I have 2 options:
Mercurial 2.1 has the largefiles extension, but I don't know too much about it. It seems like it'll solve the 'repository bloat' problem but doesn't solve binary merge conflict issues.
Keeping the binary assets in a SVN checkout, as a subrepo. This way we can lock files for editing and avoid merge conflicts, but I would really like to avoid having to use 2 version control systems (especially one that I don't really like that much).
Any insight/advice or other options I haven't thought of?
As you surmised large files will do what you need. For merging binaries you can set up a merge tool if one exists for your file type. Something like this:
[merge-tools]
mymergetool.priority = 100
mymergetool.premerge = False
mymergetool.args = $local $other $base -o $output
myimgmerge = SOME-PROGRAM-THAT-WILL-MERGE-IMAGES-FOR-YOU
[merge-patterns]
**.jpg = myimgmerge
**.exe = internal:fail
In general though, merging non-text things will always be a pain using a source control tool. Digital Asset Management applications exist to make that less painful, but they're not decentralized or very pleasant with which to work.
You're correct that the largefiles extension will avoid bloating the repository. What happens is that you only download the large files needed by the revision you're checking out. So if you have a 50 MB file and it has been edited radically 10 times, then the versions might take up 500 MB on the server. However, when you do hg update you only download the 50 MB version you need for that revision.
You're also correct that the largefiles extension doesn't help with merges. Infact, it skips the merge step completely and only prompts you like this:
largefile <some large file> has a merge conflict
keep (l)ocal or take (o)ther?
You don't get a chance to use the normal merge machinery.
To do locking, you could use the lock extension I wrote for a client. They wanted it for their documentation department where people would work with files that cannot be easily merged. It basically turns Mercurial into a centralized system similar to Subversion: locks are stored in a file in the central repository and client contact this repository when you run hg locks and before hg commit.

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

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!

What exactly does the word Patch mean when referring to 'submitting a patch'?

What exactly does the word patch mean when referring to 'submitting a patch'?
I've seen this used a lot, especially in the open source world. What what does it mean and what exactly is involved in submitting a patch?
It's a file with a list of differences between the code files that have changed. It's usually in the format generated by doing a diff -u on the two files. Most version control systems allow the easy creation of patches but it's generally in that same format.
This allows the code change to be easily applied to someone else's copy of the source code using the patch command.
For example:
Let's say I have the following code:
<?php
$foo = 0;
?>
and I change it to this:
<?php
$bar = 0;
?>
The patch file might look like this:
Index: test.php
===================================================================
--- test.php (revision 40)
+++ test.php (working copy)
## -3,7 +3,7 ##
<?php
- $foo = 0;
+ $bar= 0;
?>
Richard Jones, a developer at Red Hat, has a nice little primer on submitting code to open source projects which covers making and submitting patches.
A patch is usually a file that contains information how to change something (very often to fix a bug, but could also be an enhancement). There are different kind of patches.
A source code patch contains information how one or multiple source code files need to be modified. You can easily generate them using the diff command and you can apply them using the patch command (on Linux/UNIX systems these commands are standard).
However, there are also binary patches. A binary patch contains information how certain bytes within a binary need to be changed. Binary patches are, of course, rare in the OpenSource world, but in the early days of computers I saw them a lot to modify shipped binaries (usually to work around a bug).
Submitting a patch means you have locally fixed something and now you send the file to someone, so he can apply this patch to his local copy or to a public copy on the web, thus other users can benefit of the fix.
Patches are also often used if you have some source code that almost compiles on a certain platform, but some tiny changes are necessary to really have it compile there. Of course you could take the source, modify it and offer the modified code for download. But what if the original source changes again (e.g. bugs get fixed or small enhancements were added)? Then you had to re-download the source, apply the changes again and offer the new modified version. It's a lot of work to keep your modified source up-to-date. Instead of modifying, you create a diff between the original and your modified copy and store it on your server. If now a user wants to download and compile the app from source, he can first download the latest & greatest version of the original source, then apply your patch (so it will compile) and always has the latest version, without you having to change the patch. A problem will only arise if the original source has been changed exactly in one of the places your patch modifies. In this case the system will refuse to apply the patch and a new patch needs to be made.
A patch is a file containing all of the necessary information to turn the maintainer's source tree in to your own. It's usually created by tools like diff or svn diff or git format-patch.
Traditionally, open-source projects accept submissions from normal schlubs in the form of patches so they don't have to give others commit access to their repositories.
A patch, ususally in the form of a .patch file, is a common flat file format for transmitting the differences between two sets of code files. So if you are working on an open source project, and make code changes to files, and want to submit that to the project owner to be checked in (usually because you don't have checkin rights), you would do so via a patch.
WinMerge has this functionality built in, as do many other tools like TortoiseSVN.
A patch file represents the difference between existing source and source you've modified. It is the primary means of adding features or fixing bugs in many projects.
You create a patch using the diff command (for example).
You can then submit this patch to the development mailing list and if it received well, then a committer will apply the patch (thus automatically applying your changes) and commit the code.
Patches are applied using the patch command.
Generally it implies submitting a unified diff file with the aggregate changeset for a feature. You can read more about patches on Wikipedia. Several version control systems (svn, git, etc.) will create a patch file for you based on a changeset.
1. n. A temporary addition to a piece of code, usually as a quick-and-dirty
remedy to an existing bug or misfeature. A patch may or may not work, and may or may not
eventually be incorporated permanently into the program. Distinguished from a diff
or mod by the fact that a patch is generated by more primitive means than the rest
of the program; the classical examples are instructions modified by using the front
panel switches, and changes made directly to the binary executable of a program
originally written in an HLL. Compare one-line fix.
See the entire definition in the jargon file here
Patch is also used in the act of updating system binaries. Microsoft sends out patches all the time but they aren't source code. They are .msp files that install improved binaries. As with all computer science terms, patch is overloaded.
I've always believed the term meant a bug fix, like a knee patch Mom used to put on your holey jeans.