[RFC][PATCH] New options to choose fast-forwarding on merge.

Jan Hudec bulb at ucw.cz
Sun Nov 19 09:03:35 GMT 2006


Hello All,

I have implemented two options for the merge command, --pull and --trivial,
that allow user to choose whether trivial merge should become a pull (like in
git; with --pull) or apply the remote changes (like it currently does; with
--trivial). I also changed the default behaviour to print an error message
and abort. This allows users to configure their prefered behaviour via
aliases, while providing a conservative default.

The reason is, that I would prefer merge to automaically converge the
branches where possible (ie. do a pull instead), but I don't think it should
always do so, as other people may want to do the trivial merge.

What can be discussed is whether to make any behaviour default and only leave
one option to switch to the other one.

-- 
						 Jan 'Bulb' Hudec <bulb at ucw.cz>
-------------- next part --------------
# Bazaar revision bundle v0.8
#
# message:
#   Options --pull and --trivial for merge command.
#   
#   Default behaviour of the merge command was changed to error out if the merge
#   is trivial (local tip is common ancestor). Further, two options for merge
#   command were added:
#   --pull: If the merge is trivial, than pull will be done instead.
#   --trivial: Merge will be done even if it is trivial.
#   --pull takes precedence, ie. --pull --trivial is equivalent to just --pull.
#   
#   Fixed all tests that used run_bzr in the trivial case to pass respective
#   option (which also tests that it does not pull instead) and added two tests
#   to check that in trivial case --pull causes to pull, --trivial causes to
#   merge and default case errors out.
#   
# committer: Jan Hudec <bulb at ucw.cz>
# date: Sun 2006-11-19 09:53:29.851999998 +0100

=== modified file NEWS
--- NEWS
+++ NEWS
@@ -15,6 +15,10 @@
       location for general information, outside of a specific command.
       This includes updates for ``bzr help revisionspec`` the first topic
       included. (Goffredo Baroncelli, John Arbash Meinel, #42714)
+
+    * ``bzr merge`` will now not do a merge if local is fully merged to
+      remote. You can use old behaviour via option ``--trivial``, or falling
+      back to pull via option ``--pull``. 
       
   INTERNALS:
 

=== modified file bzrlib/builtins.py
--- bzrlib/builtins.py
+++ bzrlib/builtins.py
@@ -2250,7 +2250,13 @@
                      Option('show-base', help="Show base revision text in "
                             "conflicts"), 
                      Option('uncommitted', help='Apply uncommitted changes'
-                            ' from a working copy, instead of branch changes')]
+                            ' from a working copy, instead of branch changes'),
+                     Option('pull', help='If the branches are not diverged,'
+                            ' chage to remote revision as via pull command'),
+                     Option('trivial', help='Create merger even if pull'
+                            ' would have been possible. --pull takes'
+                            ' precedence'),
+                     ]
 
     def help(self):
         from inspect import getdoc
@@ -2258,7 +2264,7 @@
 
     def run(self, branch=None, revision=None, force=False, merge_type=None,
             show_base=False, reprocess=False, remember=False, 
-            uncommitted=False):
+            uncommitted=False, pull=False, trivial=False):
         if merge_type is None:
             merge_type = _mod_merge.Merge3Merger
 
@@ -2329,6 +2335,8 @@
                     merge_type=merge_type,
                     reprocess=reprocess,
                     show_base=show_base,
+                    pull=pull,
+                    trivial=trivial,
                     pb=pb, file_list=interesting_files)
             finally:
                 pb.finished()
@@ -2985,6 +2993,7 @@
                   this_dir=None, backup_files=False,
                   merge_type=None,
                   file_list=None, show_base=False, reprocess=False,
+                  pull=False, trivial=True,
                   pb=DummyProgress()):
     """Merge changes into a tree.
 
@@ -3039,6 +3048,17 @@
         if merger.base_rev_id == merger.other_rev_id:
             note('Nothing to do.')
             return 0
+        if file_list is None:
+            if merger.base_rev_id == merger.this_rev_id:
+                if pull:
+                    count = merger.this_tree.pull(merger.this_branch,
+                            False, merger.other_rev_id)
+                    note('%d revision(s) pulled.' % (count,))
+                    return 0
+                elif not trivial:
+                    raise errors.BzrCommandError("Local revision is ancestor to"
+                            " remote. Use pull to change to remote or merge"
+                            " --trivial to do a merge.")
         merger.backup_files = backup_files
         merger.merge_type = merge_type 
         merger.set_interesting_files(file_list)

=== modified file bzrlib/tests/blackbox/test_bound_branches.py
--- bzrlib/tests/blackbox/test_bound_branches.py
+++ bzrlib/tests/blackbox/test_bound_branches.py
@@ -326,7 +326,7 @@
         new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
 
         os.chdir('../child')
-        bzr('merge', '../other')
+        bzr('merge', '--trivial', '../other')
 
         self.failUnlessExists('c')
         tree = WorkingTree.open('.') # opens child

=== modified file bzrlib/tests/blackbox/test_log.py
--- bzrlib/tests/blackbox/test_log.py
+++ bzrlib/tests/blackbox/test_log.py
@@ -127,10 +127,10 @@
         self.run_bzr('branch', 'child', 'smallerchild')
         self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
         os.chdir('child')
-        self.run_bzr('merge', '../smallerchild')
+        self.run_bzr('merge', '--trivial', '../smallerchild')
         self.run_bzr('commit', '-m', 'merge branch 2')
         os.chdir('../parent')
-        self.run_bzr('merge', '../child')
+        self.run_bzr('merge', '--trivial', '../child')
         self.run_bzr('commit', '-m', 'merge branch 1')
         out,err = self.run_bzr('log')
         # the log will look something like:

=== modified file bzrlib/tests/blackbox/test_merge.py
--- bzrlib/tests/blackbox/test_merge.py
+++ bzrlib/tests/blackbox/test_merge.py
@@ -239,3 +239,41 @@
         tree_b.revert([])
         self.run_bzr_error(('Cannot use --uncommitted and --revision',), 
                            'merge', '../a', '--uncommitted', '-r1')
+
+    def pullable_branch(self):
+        os.mkdir('a')
+        os.chdir('a')
+        self.example_branch()
+        os.chdir('..')
+        self.runbzr('branch a b')
+        os.chdir('b')
+        file('goodbye', 'wt').write('quux')
+        self.runbzr(['commit', '-m', "mode u's are always good"])
+        os.chdir('../a')
+
+    def pullable_branch(self):
+        tree_a = self.make_branch_and_tree('a')
+        self.build_tree(['a/file'])
+        tree_a.add(['file'])
+        self.id1 = tree_a.commit('commit 1')
+        
+        tree_b = self.make_branch_and_tree('b')
+        tree_b.pull(tree_a.branch)
+        file('b/file', 'wb').write('foo')
+        self.id2 = tree_b.commit('commit 2')
+
+    def test_merge_pull(self):
+        self.pullable_branch()
+        os.chdir('a')
+        (out, err) = self.run_bzr('merge', '--pull', '../b')
+        self.assertContainsRe(err, '1 revision\\(s\\) pulled')
+        tree_a = WorkingTree.open('.')
+        self.assertEqual([self.id2], tree_a.get_parent_ids())
+
+    def test_merge_trivial(self):
+        self.pullable_branch()
+        os.chdir('a')
+        self.run_bzr_error(('pull', '--trivial'), 'merge', '../b')
+        self.run_bzr('merge', '--trivial', '../b')
+        tree_a = WorkingTree.open('.')
+        self.assertEqual([self.id1, self.id2], tree_a.get_parent_ids())

=== modified file bzrlib/tests/blackbox/test_missing.py
--- bzrlib/tests/blackbox/test_missing.py
+++ bzrlib/tests/blackbox/test_missing.py
@@ -70,7 +70,7 @@
         branch_b.unlock()
 
         # get extra revision from b
-        bzr('merge', '../b')
+        bzr('merge', '--trivial', '../b')
         bzr('commit', '-m', 'merge')
 
         # compare again, but now we have the 'merge' commit extra

=== modified file bzrlib/tests/blackbox/test_pull.py
--- bzrlib/tests/blackbox/test_pull.py
+++ bzrlib/tests/blackbox/test_pull.py
@@ -156,7 +156,7 @@
         rev_history_a = get_rh(3)
 
         os.chdir('../b')
-        bzr('merge', '../a')
+        bzr('merge', '--trivial', '../a')
         bzr('commit', '-m', 'merge')
 
         rev_history_b = get_rh(2)
@@ -198,7 +198,7 @@
         rev_history_a = get_rh(3)
 
         os.chdir('../b')
-        bzr('merge', '../a')
+        bzr('merge', '--trivial', '../a')
         bzr('commit', '-m', 'merge')
 
         rev_history_b = get_rh(2)

=== modified file bzrlib/tests/blackbox/test_too_much.py
--- bzrlib/tests/blackbox/test_too_much.py
+++ bzrlib/tests/blackbox/test_too_much.py
@@ -256,10 +256,10 @@
         self.runbzr('branch . ../branch3')
         self.runbzr('commit --unchanged --message peter')
         os.chdir('../branch2')
-        self.runbzr('merge ../branch1')
+        self.runbzr('merge --trivial ../branch1')
         self.runbzr('commit --unchanged --message pumpkin')
         os.chdir('../branch3')
-        self.runbzr('merge ../branch2')
+        self.runbzr('merge --trivial ../branch2')
         message = self.capture('status')
 
 

=== modified directory  // last-changed:bulb at ucw.cz-20061119085329-z7j0v39qmzak
... bsw9
# revision id: bulb at ucw.cz-20061119085329-z7j0v39qmzakbsw9
# sha1: c3672ceb0a837d0d4e849addcc9a87f9f74db42f
# inventory sha1: 64226bd29a96784922806cd6100a21fbc09f0b9d
# parent ids:
#   pqm at pqm.ubuntu.com-20061117041115-edacd4c4482528f6
# base id: pqm at pqm.ubuntu.com-20061117041115-edacd4c4482528f6
# properties:
#   branch-nick: bzr.pointless-merges

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20061119/b01c9bc8/attachment.pgp 


More information about the bazaar mailing list