diff --git a/hgext/rebase.py b/hgext/rebase.py
index c83d36b81df131640281c20e7100e6e8a33bc009_aGdleHQvcmViYXNlLnB5..7159426c8d13647679e47f4692d5aeb7cdf31baa_aGdleHQvcmViYXNlLnB5 100644
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -23,6 +23,7 @@
 import os, errno
 
 nullmerge = -2
+revignored = -3
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -392,6 +393,15 @@
     # have to allow merging with it.
     return merge.update(repo, rev, True, True, False, base, collapse)
 
+def nearestrebased(repo, rev, state):
+    """return the nearest ancestors of rev in the rebase result"""
+    rebased = [r for r in state if state[r] > nullmerge]
+    candidates = repo.revs('max(%ld  and (::%d))', rebased, rev)
+    if candidates:
+        return state[candidates[0]]
+    else:
+        return None
+
 def defineparents(repo, rev, target, state, targetancestors):
     'Return the new parent relationship of the revision that will be rebased'
     parents = repo[rev].parents()
@@ -403,6 +413,10 @@
     elif P1n in state:
         if state[P1n] == nullmerge:
             p1 = target
+        elif state[P1n] == revignored:
+            p1 = nearestrebased(repo, P1n, state)
+            if p1 is None:
+                p1 = target
         else:
             p1 = state[P1n]
     else: # P1n external
@@ -415,6 +429,11 @@
         if P2n in state:
             if p1 == target: # P1n in targetancestors or external
                 p1 = state[P2n]
+            elif state[P2n] == revignored:
+                p2 = nearestrebased(repo, P2n, state)
+                if p2 is None:
+                    # no ancestors rebased yet, detach
+                    p2 = target
             else:
                 p2 = state[P2n]
         else: # P2n external
@@ -532,5 +551,7 @@
                 keepbranches = bool(int(l))
             else:
                 oldrev, newrev = l.split(':')
-                if newrev != str(nullmerge):
+                if newrev in (str(nullmerge), str(revignored)):
+                    state[repo[oldrev].rev()] = int(newrev)
+                else:
                     state[repo[oldrev].rev()] = repo[newrev].rev()
@@ -536,6 +557,4 @@
                     state[repo[oldrev].rev()] = repo[newrev].rev()
-                else:
-                    state[repo[oldrev].rev()] = int(newrev)
         skipped = set()
         # recompute the set of skipped revs
         if not collapse:
@@ -658,6 +677,15 @@
     for r in detachset:
         if r not in state:
             state[r] = nullmerge
+    if len(roots) > 1:
+        # If we have multiple roots, we may have "hole" in the rebase set.
+        # Rebase roots that descend from those "hole" should not be detached as
+        # other root are. We use the special `revignored` to inform rebase that
+        # the revision should be ignored but that `defineparent` should search
+        # a rebase destination that make sense regarding rebaset topology.
+        rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset))
+        for ignored in set(rebasedomain) - set(rebaseset):
+            state[ignored] = revignored
     return repo['.'].rev(), dest.rev(), state
 
 def clearrebased(ui, repo, state, skipped, collapsedas=None):
diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t
index c83d36b81df131640281c20e7100e6e8a33bc009_dGVzdHMvdGVzdC1yZWJhc2Utb2Jzb2xldGUudA==..7159426c8d13647679e47f4692d5aeb7cdf31baa_dGVzdHMvdGVzdC1yZWJhc2Utb2Jzb2xldGUudA== 100644
--- a/tests/test-rebase-obsolete.t
+++ b/tests/test-rebase-obsolete.t
@@ -366,6 +366,6 @@
 
   $ hg rebase --dest 4 --rev '7+11+9'
   $ hg log -G
-  @  14:00891d85fcfc C
+  @  14:1e8370e38cca C
   |
   | o  13:102b4c1d889b D
@@ -370,7 +370,7 @@
   |
   | o  13:102b4c1d889b D
-  |/
-  | o  12:bfe264faf697 H
+  | |
+  o |  12:bfe264faf697 H
   |/
   | o  10:7c6027df6a99 B
   | |