changeset 156:91a936be78b8

Document merge behaviour with file names.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon, 12 Mar 2007 23:11:26 -0700
parents 914babdc99c8
children e49f4451d0e3
files en/Makefile en/daily.tex en/examples/issue29 en/examples/issue29.go.out en/examples/rename.divergent en/examples/rename.divergent.clone.out en/examples/rename.divergent.merge.out en/examples/rename.divergent.rename.anne.out en/examples/rename.divergent.rename.bob.out
diffstat 9 files changed, 161 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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 \
--- 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
--- /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
--- /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}
+
--- /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
--- /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
--- /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
--- /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'}
--- /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'}