Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How well "hg mv" command performs

Tags:

mercurial

Let's say, there is file.txt in a repo and two people are hacking it. One of them moved file.txt to another folder with hg mv and immediately pushed this into the repo. Is there any chance that Mercurial will automatically merge changes from original file.txt into the moved file.txt when the colleague decides to push its own touch ups?

Am I too optimistic?

like image 746
Stas Avatar asked Mar 04 '11 07:03

Stas


3 Answers

Short answer: Yes, you can.

Long example: a classical Java refactoring vs code change in same file

mkdir hgmv
cd hgmv/
mkdir -p com/example/hgmv/
cat << EOF > com/example/hgmv/Main.java
package com.example.hgmv;
class Main
{  
  public static void main(String args[])
  {
    System.out.println("Hello World!");
  }
}
EOF
hg init .
hg add com/example/hgmv/Main.java
hg commit -m "First working version"
cd ..
hg clone hgmv hgmv.refactor
hg clone hgmv hgmv.translation

cd hgmv.refactor
hg branch refactor
hg mv com/example/hgmv/Main.java com/example/hgmv/HgMv.java
sed -i'' 's/Main/HgMv/g' com/example/hgmv/HgMv.java
hg commit -m "refactoring Main->HgMv"
hg push -f --new-branch ../hgmv
cd ..

cd hgmv.translation
hg branch translation
sed -i'' 's/Hello World!/Bonjour Monde!/g' com/example/hgmv/Main.java
hg commit -m "french translation"
hg push -f --new-branch ../hgmv
cd ..

cd hgmv
hg up refactor
hg merge translation
hg commit -m "merge"
cat com/example/hgmv/HgMv.java

And the flaming: This is one of the strength of mercurial over git

  • Mercurial stores rename/copy at commit time.
  • Git guess rename/copy at merge time.
like image 161
shellholic Avatar answered Oct 22 '22 07:10

shellholic


This is rather easy to test, and since there are already good answers here, I'll make my answer this main point instead:

  • Experiment, experiment, experiment

Here, I'll show you how this works:

@echo off
setlocal

if exist master rd /s /q master
if exist clone rd /s /q clone
hg init master

rem Create new repository
echo a >master\test1.txt
hg commit master -m "test1" --addremove

rem Clone it
hg clone master clone

rem Now rename the file in master
cd master
hg move test1.txt test2.txt
hg commit -m "renamed"

rem And change it in clone
cd ..\clone
echo b >test1.txt
hg commit -m "changed"

rem Now pull and merge
hg pull
hg merge

Output:

[C:\Temp] :test
adding master\test1.txt
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
pulling from c:\Temp\master
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
merging test1.txt and test2.txt to test2.txt
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
like image 41
Lasse V. Karlsen Avatar answered Oct 22 '22 07:10

Lasse V. Karlsen


Mercurial stores renaming in metadatas of the repository, so when you do a hg mv OLD NEW, Mercurial keeps the information that you moved the file.

When your coworker pull the modifications from the repository, he will pull the renaming as well and Mercurial will try to merge the changes the best as he can. If you only renamed the file, there will be no problem at all, the changes from your coworker will be merger with the renaming.

However, conflicts can arise in the following situation :

  1. You modified the file too, in this case this will be the same as any conflict on a given file
  2. Your coworker renamed the file too, in this case Mercurial will ask which is the right name to use.
like image 23
krtek Avatar answered Oct 22 '22 09:10

krtek