Merge a single file in a Mercurial repository?

A DVCS operates on changesets. Thus, the merge command doesn’t even have an option for specifying a file to merge.

Jump to updates.

A file I was working on had several changes and commits into the Mercurial repository. Then I noticed that one of the previous commits removed a required line. How do I put it back? Sure just get the contents add it to the file and commit. That’s what a VCS is for. Duh. Sure, but, but, but … Shouldn’t the tools make this effortless? I should be able to just execute: “hg merge -r 0 hello.txt”. And, then have the opportunity to select the line to merge into the current working copy.

In Mercurial the workflow is to update to the revision that has the first sign of the problem, fix it, and commit. That creates another “head”, so when one subsequently merges, the missing line is in the new file, like magic. Another commit, and all is right with the world.

I like that. However, I use Mercurial in an ad hoc fashion, locally. At my employer’s the official SCM tool is CVS. Hence, I’m still in the single file revision frame of mind and a DVCS newbie.

Still, I would like to just merge a single file. The problem with the workflow is that you still have to manually fix the file. What if it is multiple lines all over a thousand line file? You still have to have a reference file to make the corrections, ie., do the visual diff and correction. What do you use to reference the needed changes, another tool, to diff the two files, the file we updated to and the revision that has the required good content, then copy that to the current work file? Sounds awkward.

Not sure if I’m stating the issue clearly here (one reason I didn’t post my question to the Mercurial forum).

Example

Create a hello.txt file and edit and commit it. We can show the contents using “hg cat” command.

hg cat -r 0 hello.txt

"Alfa"
"Bravo"
"Charlie"
"Delta"
"Echo"
"Foxtrot"

The second revision removed a line, and, the third revision added some new lines. We can show this activity with:

hg diff -r 0:2 hello.txt

diff -r 0c9f8abd05ff -r 7c15ff6962de hello.txt
--- a/hello.txt Sun Jan 16 02:46:20 2011 -0500
+++ b/hello.txt Sun Jan 16 02:48:13 2011 -0500
@@ -1,7 +1,9 @@
 "Alfa"
 "Bravo"
-"Charlie"
 "Delta"
 "Echo"
 "Foxtrot"
-
+"Golf"
+"Hotel"
+"Romeo"
+"Sierra"

We want to add that missing line 7 to the current copy of hello.txt in the working folder. With a simple example like this, we can just copy the line and add it to the file. But, if this were a complex file with hundreds of lines, that would not be very smart. In that case, we can do a “hg cat -r 0 hello.txt > hello-old.txt“. Then use a merge tool to merge the two files and add back the missing line.

This is ok, but then you have that temporary file around and even so, still doesn’t feel right.

Another approach, and I think much simpler, is to execute:

hg extdiff -p kdiff3 -r 0 hello.txt

This will invoke the kdiff3 gui in diff mode by using the extdiff Mercurial extension. In the kdiff3 merge menu select “merge current file” and your ready to roll. The destination file is already specified. Have not figured out how to use this invocation of kdiff3 in merge mode.

Note that you can’t use the merge command for this non-Mercurialish merge attempt:

hg merge -t kdiff3 -r 0

abort: merging with a working directory ancestor has no effect

After the visual merge we get:

cat hello.txt

"Alfa"
"Bravo"
"Charlie"
"Delta"
"Echo"
"Foxtrot"
"Golf"
"Hotel"
"Romeo"
"Sierra"

This is very likely NOT the way to do it in Mercurial. How should it be done? Is the prior workflow with the updates the best way? I think the real issue, honestly, is that I haven’t groked DVCS yet. I will.

Updates

Similar Posts:

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Leave a Reply

Your email address will not be published. Required fields are marked *