# HG changeset patch # User Bryan O'Sullivan # Date 1173766286 25200 # Node ID 91a936be78b8900e6a75676270eabea6f889b427 # Parent 914babdc99c8f0f8bc0940cf117d9a6bb6cb4510 Document merge behaviour with file names. diff -r 914babdc99c8 -r 91a936be78b8 en/Makefile --- a/en/Makefile Mon Mar 12 23:10:32 2007 -0700 +++ b/en/Makefile Mon Mar 12 23:11:26 2007 -0700 @@ -62,6 +62,7 @@ hook.msglen \ hook.simple \ hook.ws \ + issue29 \ mq.guards \ mq.qinit-help \ mq.dodiff \ @@ -69,6 +70,7 @@ mq.tarball \ mq.tools \ mq.tutorial \ + rename.divergent \ rollback \ template.simple \ template.svnstyle \ diff -r 914babdc99c8 -r 91a936be78b8 en/daily.tex --- a/en/daily.tex Mon Mar 12 23:10:32 2007 -0700 +++ b/en/daily.tex Mon Mar 12 23:11:26 2007 -0700 @@ -303,11 +303,11 @@ propagation of changes happens when you merge after a rename as after a copy. -If I modify a file, and you rename it to a new name, then we merge our -respective changes, my modifications to the file under its original -name will be propagated into the file under its new name. (This is -something you might expect to ``simply work,'' but not all revision -control systems actually do this.) +If I modify a file, and you rename it to a new name, and then we merge +our respective changes, my modifications to the file under its +original name will be propagated into the file under its new name. +(This is something you might expect to ``simply work,'' but not all +revision control systems actually do this.) Whereas having changes follow a copy is a feature where you can perhaps nod and say ``yes, that might be useful,'' it should be clear @@ -315,6 +315,56 @@ this facility, it would simply be too easy for changes to become orphaned when files are renamed. +\subsection{Divergent renames and merging} + +The case of diverging names occurs when two developers start with a +file---let's call it \filename{foo}---in their respective +repositories. + +\interaction{rename.divergent.clone} +Anne renames the file to \filename{bar}. +\interaction{rename.divergent.rename.anne} +Meanwhile, Bob renames it to \filename{quux}. +\interaction{rename.divergent.rename.bob} + +I like to think of this as a conflict because each developer has +expressed different intentions about what the file ought to be named. + +What do you think should happen when they merge their work? +Mercurial's actual behaviour is that it always preserves \emph{both} +names when it merges changesets that contain divergent renames. +\interaction{rename.divergent.merge} + +I personally find this behaviour quite surprising, which is why I +wanted to explicitly mention it here. I would have expected Mercurial +to prompt me with a three-way choice instead: do I want to keep only +\filename{bar}, only \filename{quux}, or both? + +In practice, when you rename a source file, it is likely that you will +also modify another file (such as a makefile) that knows how to build +the source file. So what will happen if Anne renames a file and edits +\filename{Makefile} to build it under its new name, while Bob does the +same, but chooses a different name for the file, is that after the +merge, there will be two copies of the source file in the working +directory under different names, \emph{and} a conflict in the section +of the \filename{Makefile} that both Bob and Anne edited. + +This behaviour is considered surprising by other people, too: +see~\bug{455} for details. + +\subsection{Convergent renames and merging} + +Another kind of rename conflict occurs when two people choose to +rename different \emph{source} files to the same \emph{destination}. +In this case, Mercurial runs its normal merge machinery, and lets you +guide it to a suitable resolution. + +\subsection{Other name-related corner cases} + +Mercurial has a longstanding bug in which it fails to handle a merge +where one side has a file with a given name, while another has a +directory with the same name. This is documented as~\bug{29}. +\interaction{issue29.go} %%% Local Variables: %%% mode: latex diff -r 914babdc99c8 -r 91a936be78b8 en/examples/issue29 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/issue29 Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,22 @@ +#!/bin/bash + +#$ name: go + +hg init issue29 +cd issue29 +echo a > a +hg ci -Ama +echo b > b +hg ci -Amb +hg up 0 +mkdir b +echo b > b/b +hg ci -Amc + +#$ ignore: abort: Is a directory: .* +hg merge + +#$ name: +# This error is expected from the failed merge. + +exit 0 diff -r 914babdc99c8 -r 91a936be78b8 en/examples/issue29.go.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/issue29.go.out Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,16 @@ +$ \textbf{hg init issue29} +$ \textbf{cd issue29} +$ \textbf{echo a > a} +$ \textbf{hg ci -Ama} +adding a +$ \textbf{echo b > b} +$ \textbf{hg ci -Amb} +adding b +$ \textbf{hg up 0} +0 files updated, 0 files merged, 1 files removed, 0 files unresolved +$ \textbf{mkdir b} +$ \textbf{echo b > b/b} +$ \textbf{hg ci -Amc} +adding b/b +$ \textbf{hg merge} + diff -r 914babdc99c8 -r 91a936be78b8 en/examples/rename.divergent --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/rename.divergent Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,33 @@ +#!/bin/bash + +hg init orig +cd orig +echo foo > foo +hg ci -A -m 'First commit' +cd .. + +#$ name: clone + +hg clone orig anne +hg clone orig bob + +#$ name: rename.anne + +cd anne +hg mv foo bar +hg ci -m 'Rename foo to bar' + +#$ name: rename.bob + +cd ../bob +hg mv foo quux +hg ci -m 'Rename foo to quux' + +#$ name: merge +# See http://www.selenic.com/mercurial/bts/issue455 + +cd ../orig +hg pull -u ../anne +hg pull ../bob +hg merge +ls diff -r 914babdc99c8 -r 91a936be78b8 en/examples/rename.divergent.clone.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/rename.divergent.clone.out Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,4 @@ +$ \textbf{hg clone orig anne} +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +$ \textbf{hg clone orig bob} +1 files updated, 0 files merged, 0 files removed, 0 files unresolved diff -r 914babdc99c8 -r 91a936be78b8 en/examples/rename.divergent.merge.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/rename.divergent.merge.out Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,23 @@ +# See http://www.selenic.com/mercurial/bts/issue455 +$ \textbf{cd ../orig} +$ \textbf{hg pull -u ../anne} +pulling from ../anne +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +1 files updated, 0 files merged, 1 files removed, 0 files unresolved +$ \textbf{hg pull ../bob} +pulling from ../bob +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) +$ \textbf{hg merge} +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +$ \textbf{ls} +bar quux diff -r 914babdc99c8 -r 91a936be78b8 en/examples/rename.divergent.rename.anne.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/rename.divergent.rename.anne.out Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,3 @@ +$ \textbf{cd anne} +$ \textbf{hg mv foo bar} +$ \textbf{hg ci -m 'Rename foo to bar'} diff -r 914babdc99c8 -r 91a936be78b8 en/examples/rename.divergent.rename.bob.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/rename.divergent.rename.bob.out Mon Mar 12 23:11:26 2007 -0700 @@ -0,0 +1,3 @@ +$ \textbf{cd ../bob} +$ \textbf{hg mv foo quux} +$ \textbf{hg ci -m 'Rename foo to quux'}