Patchwork [1,of,3,two-rebase-fixes] rebase: do not invent successor to skipped changeset

login
register
mail settings
Submitter Pierre-Yves David
Date Jan. 18, 2013, 10:50 p.m.
Message ID <b988bbf2c7783ff96aae.1358549457@yamac.lan>
Download mbox | patch
Permalink /patch/678/
State Accepted
Commit 55aff0c2b73cee834b6c2b6123a74597555e96d0
Headers show

Comments

Pierre-Yves David - Jan. 18, 2013, 10:50 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
# Date 1358514932 -3600
# Node ID b988bbf2c7783ff96aaef6a1a6dc025d140de975
# Parent  1f794204abbd7dd4bc329ae0c7c4fd7ce56b33af
rebase: do not invent successor to skipped changeset

When rebase results in an empty a changeset it is "skipped" and no related
changeset is created at all. When we added obsolescence support to rebase (in
fc2a6114f0a0) it seemed a good idea to use its parent successor as the
successors for such dropped changesets. (see old version of the altered test).
This option was chosen because it seems a good way to hint about were the
dropped changeset "intended" to be. Such hint would have been used by automatic
evolution mechanism to rebase potential unstable children.

However, field testing of this version are not conclusive. It very often leads
to the creation of (totally unfounded) evolution divergence. This changeset
changes this behavior and mark skipped changesets as pruned (obsolete without
successors). This prevents the issue and seems semantically better probably a
win for obsolescence reading tool.

See example bellow for details:

User Babar has five changesets of interest:
- O, its current base of development.
- U, the new upstream
- A and C, some development changesets
- B another development changeset independent from A

    O - A - B - C
      \
        U

Babar decides that B is more critical than the A and C and rebase it first

  $ hg rebase --rev B --dest U

B is now obsolete (in lower case bellow). Rebase result, B', is its
successors.(note, C is unstable)

    O - A - b - C
      \
        U - B'

Babar is now done with B', and want to rebase the rest of its history:

  $ hg rebase --source A --dest B'


hg rebase process A, B and C. B is skipped as all its changes are already contained
in B'.

    O - U - B' - A' - C'

Babar have the expected result graph wise, obsolescence marker are as follow:

    B -> B' (from first rebase)
    A -> A' (from second rebase)
    C -> C' (from second rebase)
    B -> ?? (from second rebase)

Before this changeset, the last marker is `B -> A'`. This cause two issues:

- This is semantically wrong. B have nothing to do with A'
- B has now two successors sets: (B',) and (A',). We detect a divergent
  rewriting. The B' and A' are reported as "divergent" to Babar, confusion
  ensues. In addition such divergent situation (divergent changeset are children
  to each other) is tricky to solve.

With this changeset the last marker is `B -> ΓΈ`:

- This is semantically better.
- B has a single successors set (B',)

This scenario is added to the tests suite.
Matt Mackall - Jan. 19, 2013, 12:49 a.m.
On Fri, 2013-01-18 at 23:50 +0100, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@ens-lyon.org>
> # Date 1358514932 -3600
> # Node ID b988bbf2c7783ff96aaef6a1a6dc025d140de975
> # Parent  1f794204abbd7dd4bc329ae0c7c4fd7ce56b33af
> rebase: do not invent successor to skipped changeset

This one is queued for default, thanks. Still trying to understand 2 and
3.

Patch

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -310,11 +310,11 @@  def rebase(ui, repo, **opts):
 
         if not keepf:
             collapsedas = None
             if collapsef:
                 collapsedas = newrev
-            clearrebased(ui, repo, state, collapsedas)
+            clearrebased(ui, repo, state, skipped, collapsedas)
 
         if currentbookmarks:
             updatebookmarks(repo, nstate, currentbookmarks, **opts)
 
         clearstatus(repo)
@@ -658,22 +658,26 @@  def buildstate(repo, dest, rebaseset, co
     for r in detachset:
         if r not in state:
             state[r] = nullmerge
     return repo['.'].rev(), dest.rev(), state
 
-def clearrebased(ui, repo, state, collapsedas=None):
+def clearrebased(ui, repo, state, skipped, collapsedas=None):
     """dispose of rebased revision at the end of the rebase
 
     If `collapsedas` is not None, the rebase was a collapse whose result if the
     `collapsedas` node."""
     if obsolete._enabled:
         markers = []
         for rev, newrev in sorted(state.items()):
             if newrev >= 0:
-                if collapsedas is not None:
-                    newrev = collapsedas
-                markers.append((repo[rev], (repo[newrev],)))
+                if rev in skipped:
+                    succs = ()
+                elif collapsedas is not None:
+                    succs = (repo[collapsedas],)
+                else:
+                    succs = (repo[newrev],)
+                markers.append((repo[rev], succs))
         if markers:
             obsolete.createmarkers(repo, markers)
     else:
         rebased = [rev for rev in state if state[rev] != nullmerge]
         if rebased:
diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t
--- a/tests/test-rebase-obsolete.t
+++ b/tests/test-rebase-obsolete.t
@@ -164,15 +164,70 @@  set.
   | x  1:42ccdea3bb16 B
   |/
   o  0:cd010b8cd998 A
   
   $ hg debugobsolete
-  42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 08483444fef91d6224f6655ee586a65d263ad34c 0 {'date': '*', 'user': 'test'} (glob)
+  42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob)
   5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob)
-  32af7686d403cf45b5d95f2d70cebea587ac806a 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob)
+  32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob)
 
 
+More complex case were part of the rebase set were already rebased
+
+  $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
+  $ hg debugobsolete
+  42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob)
+  5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob)
+  32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob)
+  08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
+  $ hg log -G
+  @  11:cbc07f266875 D
+  |
+  | o  10:5ae4c968c6ac C
+  | |
+  | x  9:08483444fef9 D
+  | |
+  | o  8:8877864f1edb B
+  | |
+  o |  7:02de42196ebe H
+  | |
+  | o  6:eea13746799a G
+  |/|
+  o |  5:24b6387c8c8c F
+  | |
+  | o  4:9520eea781bc E
+  |/
+  o  0:cd010b8cd998 A
+  
+  $ hg rebase --source 'desc(B)' --dest 'tip'
+  $ hg debugobsolete
+  42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '* *', 'user': 'test'} (glob)
+  5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '* *', 'user': 'test'} (glob)
+  32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '* *', 'user': 'test'} (glob)
+  08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
+  8877864f1edb05d0e07dc4ba77b67a80a7b86672 b1861c79d66ec3aa1b607ac3c9fb819e38b12238 0 {'date': '* *', 'user': 'test'} (glob)
+  08483444fef91d6224f6655ee586a65d263ad34c 0 {'date': '* *', 'user': 'test'} (glob)
+  5ae4c968c6aca831df823664e706c9d4aa34473d dd4be135457a404ce5541de427ae1d98a28f4acd 0 {'date': '* *', 'user': 'test'} (glob)
+  $ hg log --rev 'divergent()'
+  $ hg log -G
+  @  13:dd4be135457a C
+  |
+  o  12:b1861c79d66e B
+  |
+  o  11:cbc07f266875 D
+  |
+  o  7:02de42196ebe H
+  |
+  | o  6:eea13746799a G
+  |/|
+  o |  5:24b6387c8c8c F
+  | |
+  | o  4:9520eea781bc E
+  |/
+  o  0:cd010b8cd998 A
+  
+
   $ cd ..
 
 collapse rebase
 ---------------------------------
 
@@ -327,5 +382,6 @@  Test multiple root handling
   | |
   o |  4:9520eea781bc E
   |/
   o  0:cd010b8cd998 A
   
+  $ cd ..