diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_bWVyY3VyaWFsL2xvY2FscmVwby5weQ==..966702174568db9a830efd8e710ea2cdb791936d_bWVyY3VyaWFsL2xvY2FscmVwby5weQ== 100644
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -100,7 +100,9 @@
 urlerr = util.urlerr
 urlreq = util.urlreq
 
-RE_SKIP_DIRSTATE_ROLLBACK = re.compile(b"^(dirstate|narrowspec.dirstate).*")
+RE_SKIP_DIRSTATE_ROLLBACK = re.compile(
+    b"^((dirstate|narrowspec.dirstate).*|branch$)"
+)
 
 # set of (path, vfs-location) tuples. vfs-location is:
 # - 'plain for vfs relative paths
@@ -2671,6 +2673,13 @@
         # strip" to pick a working copy destination on `hg rollback`
         if self.currentwlock() is not None:
             ds = self.dirstate
+            if ds.branch() == b'default':
+                # force a file to be written if None exist
+                ds.setbranch(b'default')
+            # we cannot simply add "branch" to `all_file_names` because branch
+            # is written outside of the transaction control. So we need to
+            # backup early.
+            tr.addbackup(b"branch", hardlink=True, location=b'plain')
 
             def backup_dirstate(tr):
                 for f in ds.all_file_names():
@@ -2685,7 +2694,6 @@
     def _journalfiles(self):
         return (
             (self.svfs, b'journal'),
-            (self.vfs, b'journal.branch'),
             (self.vfs, b'journal.desc'),
         )
 
@@ -2694,9 +2702,6 @@
 
     @unfilteredmethod
     def _writejournal(self, desc):
-        self.vfs.write(
-            b"journal.branch", encoding.fromlocal(self.dirstate.branch())
-        )
         self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
 
     def recover(self):
@@ -2799,18 +2804,6 @@
                     self.dirstate.setparents(self.nullid)
                     self.dirstate.clear()
 
-            try:
-                branch = self.vfs.read(b'undo.branch')
-                self.dirstate.setbranch(encoding.tolocal(branch))
-            except IOError:
-                ui.warn(
-                    _(
-                        b'named branch could not be reset: '
-                        b'current branch is still \'%s\'\n'
-                    )
-                    % self.dirstate.branch()
-                )
-
             parents = tuple([p.rev() for p in self[None].parents()])
             if len(parents) > 1:
                 ui.status(
diff --git a/mercurial/shelve.py b/mercurial/shelve.py
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_bWVyY3VyaWFsL3NoZWx2ZS5weQ==..966702174568db9a830efd8e710ea2cdb791936d_bWVyY3VyaWFsL3NoZWx2ZS5weQ== 100644
--- a/mercurial/shelve.py
+++ b/mercurial/shelve.py
@@ -440,6 +440,7 @@
     # These is not such other wrapping currently, but if someone try to
     # implement one in the future, this will explicitly break here instead of
     # misbehaving in subtle ways.
+    current_branch = ds.branch()
     assert 'invalidate' not in vars(ds)
     try:
         # note : we could simply disable the transaction abort callback, but
@@ -452,6 +453,7 @@
     # transaction to do so.
     assert repo.currenttransaction() is None
     repo.dirstate.write(None)
+    ds.setbranch(current_branch)
 
 
 def getshelvename(repo, parent, opts):
diff --git a/mercurial/transaction.py b/mercurial/transaction.py
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_bWVyY3VyaWFsL3RyYW5zYWN0aW9uLnB5..966702174568db9a830efd8e710ea2cdb791936d_bWVyY3VyaWFsL3RyYW5zYWN0aW9uLnB5 100644
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -692,6 +692,10 @@
         if entries:
             return False
         for e in self._backupentries:
+            if e[0] == b'plain' and e[1] == b'branch':
+                # XXX integrate branch to the transaction and get rid of this
+                # aberration
+                continue
             if e[1]:
                 return False
         return True
@@ -701,7 +705,9 @@
         assert self._can_quick_abort(entries)
         tmp_files = [e for e in self._backupentries if not e[1]]
         for vfs_id, old_path, tmp_path, xxx in tmp_files:
-            assert not old_path
+            # XXX integrate branch to the transaction and get rid of this
+            # aberration
+            assert not old_path or old_path == b'branch'
             vfs = self._vfsmap[vfs_id]
             try:
                 vfs.unlink(tmp_path)
diff --git a/tests/test-empty.t b/tests/test-empty.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1lbXB0eS50..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1lbXB0eS50 100644
--- a/tests/test-empty.t
+++ b/tests/test-empty.t
@@ -35,7 +35,8 @@
   $ hg verify -q
   $ ls .hg
   00changelog.i
+  branch
   cache
   hgrc
   requires
   store
@@ -38,7 +39,8 @@
   cache
   hgrc
   requires
   store
+  undo.backup.branch
   wcache
 
 Should be empty (except for the "basic" requires):
diff --git a/tests/test-fncache.t b/tests/test-fncache.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1mbmNhY2hlLnQ=..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1mbmNhY2hlLnQ= 100644
--- a/tests/test-fncache.t
+++ b/tests/test-fncache.t
@@ -90,6 +90,7 @@
   .hg
   .hg/00changelog.i
   .hg/00manifest.i
+  .hg/branch
   .hg/cache
   .hg/cache/branch2-served
   .hg/cache/rbc-names-v1
@@ -103,4 +104,5 @@
   .hg/phaseroots
   .hg/requires
   .hg/undo
+  .hg/undo.backup.branch
   .hg/undo.backupfiles
@@ -106,5 +108,4 @@
   .hg/undo.backupfiles
-  .hg/undo.branch
   .hg/undo.desc
   .hg/wcache
   .hg/wcache/checkisexec (execbit !)
@@ -124,6 +125,7 @@
   $ find .hg | sort
   .hg
   .hg/00changelog.i
+  .hg/branch
   .hg/cache
   .hg/cache/branch2-served
   .hg/cache/rbc-names-v1
@@ -142,7 +144,7 @@
   .hg/store/requires
   .hg/store/undo
   .hg/store/undo.backupfiles
-  .hg/undo.branch
+  .hg/undo.backup.branch
   .hg/undo.desc
   .hg/wcache
   .hg/wcache/checkisexec (execbit !)
diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1oYXJkbGlua3MudA==..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1oYXJkbGlua3MudA== 100644
--- a/tests/test-hardlinks.t
+++ b/tests/test-hardlinks.t
@@ -227,7 +227,7 @@
 
   $ nlinksdir r4
   2 r4/.hg/00changelog.i
-  2 r4/.hg/branch
+  [24] r4/.hg/branch (re)
   2 r4/.hg/cache/branch2-base
   2 r4/.hg/cache/branch2-immutable
   2 r4/.hg/cache/branch2-served
@@ -256,4 +256,5 @@
   2 r4/.hg/store/undo.backup.fncache (repofncache !)
   2 r4/.hg/store/undo.backup.phaseroots
   2 r4/.hg/store/undo.backupfiles
+  [24] r4/.hg/undo.backup.branch (re)
   2 r4/\.hg/undo\.backup\.dirstate (re)
@@ -259,5 +260,4 @@
   2 r4/\.hg/undo\.backup\.dirstate (re)
-  2 r4/.hg/undo.branch
   2 r4/.hg/undo.desc
   2 r4/.hg/wcache/checkisexec (execbit !)
   2 r4/.hg/wcache/checklink-target (symlink !)
@@ -311,4 +311,5 @@
   2 r4/.hg/store/undo.backup.fncache (repofncache !)
   2 r4/.hg/store/undo.backup.phaseroots
   2 r4/.hg/store/undo.backupfiles
+  [23] r4/.hg/undo.backup.branch (re)
   2 r4/\.hg/undo\.backup\.dirstate (re)
@@ -314,5 +315,4 @@
   2 r4/\.hg/undo\.backup\.dirstate (re)
-  2 r4/.hg/undo.branch
   2 r4/.hg/undo.desc
   2 r4/.hg/wcache/checkisexec (execbit !)
   2 r4/.hg/wcache/checklink-target (symlink !)
diff --git a/tests/test-inherit-mode.t b/tests/test-inherit-mode.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1pbmhlcml0LW1vZGUudA==..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1pbmhlcml0LW1vZGUudA== 100644
--- a/tests/test-inherit-mode.t
+++ b/tests/test-inherit-mode.t
@@ -68,6 +68,7 @@
   $ "$PYTHON" ../printmodes.py .
   00700 ./.hg/
   00600 ./.hg/00changelog.i
+  00660 ./.hg/branch
   00770 ./.hg/cache/
   00660 ./.hg/cache/branch2-served
   00660 ./.hg/cache/rbc-names-v1
@@ -94,7 +95,7 @@
   00600 ./.hg/store/requires
   00660 ./.hg/store/undo
   00660 ./.hg/store/undo.backupfiles
-  00660 ./.hg/undo.branch
+  00660 ./.hg/undo.backup.branch
   00660 ./.hg/undo.desc
   00770 ./.hg/wcache/
   00711 ./.hg/wcache/checkisexec
@@ -129,6 +130,7 @@
   $ "$PYTHON" ../printmodes.py ../push
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
+  00660 ../push/.hg/branch
   00770 ../push/.hg/cache/
   00660 ../push/.hg/cache/branch2-base
   00660 ../push/.hg/cache/rbc-names-v1
@@ -151,7 +153,7 @@
   00660 ../push/.hg/store/requires
   00660 ../push/.hg/store/undo
   00660 ../push/.hg/store/undo.backupfiles
-  00660 ../push/.hg/undo.branch
+  00660 ../push/.hg/undo.backup.branch
   00660 ../push/.hg/undo.desc
   00770 ../push/.hg/wcache/
 
diff --git a/tests/test-largefiles-small-disk.t b/tests/test-largefiles-small-disk.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1sYXJnZWZpbGVzLXNtYWxsLWRpc2sudA==..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1sYXJnZWZpbGVzLXNtYWxsLWRpc2sudA== 100644
--- a/tests/test-largefiles-small-disk.t
+++ b/tests/test-largefiles-small-disk.t
@@ -10,7 +10,7 @@
   > _origcopyfileobj = shutil.copyfileobj
   > def copyfileobj(fsrc, fdst, length=16 * 1024):
   >     # allow journal files (used by transaction) to be written
-  >     if b'journal.' in fdst.name:
+  >     if b'journal.' in fdst.name or b'backup.' in fdst.name:
   >         return _origcopyfileobj(fsrc, fdst, length)
   >     fdst.write(fsrc.read(4))
   >     raise IOError(errno.ENOSPC, os.strerror(errno.ENOSPC))
diff --git a/tests/test-rollback.t b/tests/test-rollback.t
index fb4a716db129c2ceb5b1eeeff88f9fefc935927e_dGVzdHMvdGVzdC1yb2xsYmFjay50..966702174568db9a830efd8e710ea2cdb791936d_dGVzdHMvdGVzdC1yb2xsYmFjay50 100644
--- a/tests/test-rollback.t
+++ b/tests/test-rollback.t
@@ -42,5 +42,4 @@
   $ cat .hg/last-message.txt ; echo
   modify a
 
-Test rollback of hg before issue 902 was fixed
 
@@ -46,12 +45,5 @@
 
-  $ hg commit -m "test3"
-  $ hg branch test
-  marked working directory as branch test
-  (branches are permanent and global, did you want a bookmark?)
-  $ rm .hg/undo.branch
-  $ hg rollback
-  repository tip rolled back to revision 0 (undo commit)
-  named branch could not be reset: current branch is still 'test'
-  working directory now based on revision 0
+working dir unaffected by rollback: do not restore dirstate et. al.
+  $ hg branch test --quiet
   $ hg branch
   test
@@ -56,7 +48,5 @@
   $ hg branch
   test
-
-working dir unaffected by rollback: do not restore dirstate et. al.
   $ hg log --template '{rev}  {branch}  {desc|firstline}\n'
   0  default  add a again
   $ hg status
@@ -82,7 +72,7 @@
   $ hg update bar
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   (activating bookmark bar)
-  $ cat .hg/undo.branch ; echo
+  $ cat .hg/undo.backup.branch
   test
   $ hg log -G --template '{rev}  [{branch}] ({bookmarks}) {desc|firstline}\n'
   o  2  [test] (foo) add b