diff --git a/hgext/transplant.py b/hgext/transplant.py
index 800e090e9c64a58d6ae312f2d8c2565a605fe322_aGdleHQvdHJhbnNwbGFudC5weQ==..99e88320d665e42d5da4d0090b764404d8151e15_aGdleHQvdHJhbnNwbGFudC5weQ== 100644
--- a/hgext/transplant.py
+++ b/hgext/transplant.py
@@ -125,6 +125,6 @@
         diffopts = patch.difffeatureopts(self.ui, opts)
         diffopts.git = True
 
-        lock = wlock = tr = None
+        lock = wlock = tr = dsguard = None
         try:
             wlock = repo.wlock()
@@ -129,5 +129,6 @@
         try:
             wlock = repo.wlock()
+            dsguard = cmdutil.dirstateguard(repo, 'transplant')
             lock = repo.lock()
             tr = repo.transaction('transplant')
             for rev in revs:
@@ -200,6 +201,7 @@
                             # Do not rollback, it is up to the user to
                             # fix the merge or cancel everything
                             tr.close()
+                            dsguard.close()
                             raise
                         if n and domerge:
                             self.ui.status(_('%s merged at %s\n') % (revstr,
@@ -212,6 +214,7 @@
                         if patchfile:
                             os.unlink(patchfile)
             tr.close()
+            dsguard.close()
             if pulls:
                 exchange.pull(repo, source.peer(), heads=pulls)
                 merge.update(repo, pulls[-1], False, False, None)
@@ -220,7 +223,10 @@
             self.transplants.write()
             if tr:
                 tr.release()
-            lock.release()
+            if lock:
+                lock.release()
+            if dsguard:
+                dsguard.release()
             wlock.release()
 
     def filter(self, filter, node, changelog, patchfile):
diff --git a/tests/test-transplant.t b/tests/test-transplant.t
index 800e090e9c64a58d6ae312f2d8c2565a605fe322_dGVzdHMvdGVzdC10cmFuc3BsYW50LnQ=..99e88320d665e42d5da4d0090b764404d8151e15_dGVzdHMvdGVzdC10cmFuc3BsYW50LnQ= 100644
--- a/tests/test-transplant.t
+++ b/tests/test-transplant.t
@@ -867,6 +867,7 @@
   > [hooks]
   > fakedirstatewritetime = !
   > fakepatchtime = !
+  > [extensions]
   > abort = !
   > EOF
 
@@ -877,4 +878,41 @@
   $ hg status -A r1
   M r1
 
+Test that rollback by unexpected failure after transplanting the first
+revision restores dirstate correctly.
+
+  $ hg rollback -q
+  $ rm -f abort
+  $ hg update -q -C d11e3596cc1a
+  $ hg parents -T "{node|short}\n"
+  d11e3596cc1a
+  $ hg status -A
+  C r1
+  C r2
+
+  $ cat >> .hg/hgrc <<EOF
+  > [hooks]
+  > # emulate failure at transplanting the 2nd revision
+  > pretxncommit.abort = test ! -f abort
+  > EOF
+  $ hg transplant "22c515968f13::"
+  applying 22c515968f13
+  22c515968f13 transplanted to * (glob)
+  applying e38700ba9dd3
+  transaction abort!
+  rollback completed
+  abort: pretxncommit.abort hook exited with status 1
+  [255]
+  $ cat >> .hg/hgrc <<EOF
+  > [hooks]
+  > pretxncommit.abort = !
+  > EOF
+
+  $ hg parents -T "{node|short}\n"
+  d11e3596cc1a
+  $ hg status -A
+  M r1
+  ? abort
+  C r2
+
   $ cd ..