Merge problems after moving directories in a branch

Gustavo Narea gustavonarea at 2degreesnetwork.com
Thu Apr 1 04:41:24 CDT 2010


Hello, Martin et al.

It's funny, before starting to write this email, another merge went
wrong. This time with a different branch.

We have a permanent branch called "staging" where we test/correct
changes before merging them into the stable "trunk". Until a few hours
ago, it had 1 revision pending to be merged into trunk: I had renamed a
directory (early this week).

A few minutes ago, a colleague, who had an up-to-date version of trunk,
changed a file in the directory renamed in staging. Then he tried to
push this change to staging, which failed because his branch wasn't in
synch with staging, so he merged staging into his local branch, and he
got the usual message:
===
remote changed old-directory/document.html which local deleted
use (c)hanged version or leave (d)eleted?
===

"old-directory/document.html" is the document he edited today, but early
this week I renamed "old-directory" to "new-directory". Mercurial
should've moved "old-directory/document.html" to
"new-directory/document.html", not ask him either to leave the file at
the old location (recreating the old directory) or loose the changes he
made.

I just tried your script on my machine (Mercurial 1.5) and my
colleague's machine (Mercurial 1.3.1), and it worked perfectly: there
was no merge problem.

So it seems like it's either a problem with our branch or a bug in
Mercurial in more complex scenarios. Should I "upgrade" the branch
somehow? It was created in 2008.

Cheers,

 - Gustavo.


On 31/03/10 20:16, Martin Geisler wrote:
>>> Could you please be more specific? Can you reproduce a bad merge with
>>> a small example?
>>>       
>> We've had this problem at least twice this year, when many files were
>> renamed/moved in one branch. This is how we got the latest bad merge:
>>
>> We have a mainline development branch (trunk). Two weeks ago I cloned
>> trunk to clean it up by rearranging many directories and removing
>> unused files/directories, among other things. I use Mercurial 1.5 and
>> my colleagues use slightly older versions.
>>     
> Okay, sounds all good.
>
>   
>> The cleanup branch is still unstable, so it cannot be merged into
>> trunk yet. I had not pulled from trunk and trunk has gotten a few
>> changes since I cloned it, but yesterday I needed to get those changes
>> applied to my cleanup branch, so I tried to merge trunk into my branch
>> and many things went wrong -- to sum up: Old directories were
>> recreated if someone added/changed directories/files in trunk to a
>> directory I renamed in cleanup. And of course, these directories
>> contained the files that were edited/added in trunk.
>>
>> I got messages like:
>> ===
>> remote changed foo-directory/file.ext which local deleted
>> use (c)hanged version or leave (d)eleted?
>> ===
>>     
> Yeah, that is unhelpful.
>
>   
>> I would expect Mercurial to be aware that "foo-directory" was renamed
>> to "bar-directory" in my local branch and thus it could update
>> "bar-directory/file.ext" automatically, instead of giving me two
>> unsuitable options: Put the file with the latest changes from trunk at
>> the wrong/old location or loose the changes. Likewise, if someone
>> added "foo-directory/new-file", I would expect Mercurial to put it at
>> "bar-directory/new-file".
>>     
> Exactly! I see exactly the behavior you want when I run the attached
> script. It gives output like this:
>
>   + hg init trunk
>   + cd trunk
>   + mkdir dir-a
>   + echo test > dir-a/a.txt
>   + echo test > dir-a/b.txt
>   + hg add
>   adding dir-a/a.txt
>   adding dir-a/b.txt
>   + hg commit -m 'Added dir.'
>   + cd ..
>   + hg clone trunk branch
>   updating to branch default
>   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>   + cd branch
>   + echo more test >> dir-a/a.txt
>   + hg commit -m 'branch commit'
>   + hg rename dir-a dir-b
>   moving dir-a/a.txt to dir-b/a.txt
>   moving dir-a/b.txt to dir-b/b.txt
>   + hg commit -m 'dir rename'
>   + cd ../trunk
>   + echo test >> dir-a/b.txt
>   + hg commit -m 'trunk commit'
>   + echo test >> dir-a/c.txt
>   + hg add
>   adding dir-a/c.txt
>   + hg commit -m 'new dir-a file'
>   + cd ../branch
>   + hg pull
>   pulling from /tmp/trunk
>   searching for changes
>   adding changesets
>   adding manifests
>   adding file changes
>   added 2 changesets with 2 changes to 2 files (+1 heads)
>   (run 'hg heads' to see heads, 'hg merge' to merge)
>   + hg merge
>   merging dir-b/b.txt and dir-a/b.txt to dir-b/b.txt
>   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
>   (branch merge, don't forget to commit)
>   + ls
>   dir-b
>   + ls dir-b
>   a.txt  b.txt  c.txt
>
>   
>
>
>
>   
>> This gets a lot worse if, for example, I modified
>> bar-directory/file.ext before the merge. I would have to find the
>> files at the new and old locations, merge the changes manually and
>> then remove the file from the old location. And it gets *even worse*
>> when there are subdirectories involved, because what used to be
>> "foo/bar/baz/file.ext" can now be "abc/xyz/file.ext".
>>     
> Very, very strange... I cannot reproduce even your simple problems.
>
>   
>> I had moved ~20 directories which affected around 1,500 files (and who
>> knows how many hundreds of sub-directories), and made tiny changes to
>> over 3,000 files (1-2 changes per file) and many of those modified
>> files are in the renamed directories. As you would imagine, it was a
>> nightmare.
>>
>> We all move files/directories by using the "hg mv" command. No-one
>> here does something like "cp source target; hg add target; hg rm
>> source;".
>>     
> Right. I just tried changing the script to do
>
>   mkdir dir-b
>   hg rename dir-a/a.txt dir-b/a.txt
>   hg commit -m 'a.txt rename'
>   hg rename dir-a/b.txt dir-b/b.txt
>   hg commit -m 'b.txt rename'
>
> instead in the branch. That does not change anything, i.e., it is only
> important that all files from dir-a were moved to dir-b for Mercurial to
> say that dir-a was renamed to dir-b.
>
>   
>> Is this a limitation in Mercurial or we're doing something wrong?
>>     
> I don't know what is going wrong... but Mercurial is definitely capable
> of merging renamed files correctly, just like Bazaar and other modern
> systems are.
>
>   

-- 
Gustavo Narea.
Software Developer.
2degrees, Ltd. <http://www.2degreesnetwork.com/>.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial/attachments/20100401/7479e6e6/attachment.htm>


More information about the Mercurial mailing list