diff --git a/hgext/mq.py b/hgext/mq.py
index b2ca2f40c9c1aa0e528381b3d10920915aaed527_aGdleHQvbXEucHk=..435375cc0ca085dea6a838a956a8eff1103828da_aGdleHQvbXEucHk= 100644
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -554,10 +554,10 @@
         except OSError, inst:
             self.ui.warn(_('error removing undo: %s\n') % str(inst))
 
-    def backup(self, repo, files):
+    def backup(self, repo, files, copy=False):
         # backup local changes in --force case
         for f in sorted(files):
             absf = repo.wjoin(f)
             if os.path.lexists(absf):
                 self.ui.note(_('saving current version of %s as %s\n') %
                              (f, f + '.orig'))
@@ -558,10 +558,13 @@
         # backup local changes in --force case
         for f in sorted(files):
             absf = repo.wjoin(f)
             if os.path.lexists(absf):
                 self.ui.note(_('saving current version of %s as %s\n') %
                              (f, f + '.orig'))
-                util.rename(absf, absf + '.orig')
+                if copy:
+                    util.copyfile(absf, absf + '.orig')
+                else:
+                    util.rename(absf, absf + '.orig')
 
     def printdiff(self, repo, diffopts, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
@@ -677,7 +680,8 @@
             return (False, list(files), False)
 
     def apply(self, repo, series, list=False, update_status=True,
-              strict=False, patchdir=None, merge=None, all_files=None):
+              strict=False, patchdir=None, merge=None, all_files=None,
+              tobackup=None):
         wlock = lock = tr = None
         try:
             wlock = repo.wlock()
@@ -685,7 +689,8 @@
             tr = repo.transaction("qpush")
             try:
                 ret = self._apply(repo, series, list, update_status,
-                                  strict, patchdir, merge, all_files=all_files)
+                                  strict, patchdir, merge, all_files=all_files,
+                                  tobackup=tobackup)
                 tr.close()
                 self.savedirty()
                 return ret
@@ -702,9 +707,14 @@
             self.removeundo(repo)
 
     def _apply(self, repo, series, list=False, update_status=True,
-               strict=False, patchdir=None, merge=None, all_files=None):
-        '''returns (error, hash)
-        error = 1 for unable to read, 2 for patch failed, 3 for patch fuzz'''
+               strict=False, patchdir=None, merge=None, all_files=None,
+               tobackup=None):
+        """returns (error, hash)
+
+        error = 1 for unable to read, 2 for patch failed, 3 for patch
+        fuzz. tobackup is None or a set of files to backup before they
+        are modified by a patch.
+        """
         # TODO unify with commands.py
         if not patchdir:
             patchdir = self.path
@@ -736,6 +746,11 @@
                 message = '\n'.join(message)
 
             if ph.haspatch:
+                if tobackup:
+                    touched = patchmod.changedfiles(self.ui, repo, pf)
+                    touched = set(touched) & tobackup
+                    self.backup(repo, touched, copy=True)
+                    tobackup = tobackup - touched
                 (patcherr, files, fuzz) = self.patch(repo, pf)
                 if all_files is not None:
                     all_files.update(files)
@@ -1241,9 +1256,14 @@
             else:
                 end = self.series.index(patch, start) + 1
 
+            tobackup = set()
+            if force:
+                m, a, r, d = self.checklocalchanges(repo, force=True)
+                tobackup.update(m + a)
+
             s = self.series[start:end]
             all_files = set()
             try:
                 if mergeq:
                     ret = self.mergepatch(repo, mergeq, s, diffopts)
                 else:
@@ -1244,10 +1264,11 @@
             s = self.series[start:end]
             all_files = set()
             try:
                 if mergeq:
                     ret = self.mergepatch(repo, mergeq, s, diffopts)
                 else:
-                    ret = self.apply(repo, s, list, all_files=all_files)
+                    ret = self.apply(repo, s, list, all_files=all_files,
+                                     tobackup=tobackup)
             except:
                 self.ui.warn(_('cleaning up working directory...'))
                 node = repo.dirstate.p1()
diff --git a/tests/test-mq-qpush-fail.t b/tests/test-mq-qpush-fail.t
index b2ca2f40c9c1aa0e528381b3d10920915aaed527_dGVzdHMvdGVzdC1tcS1xcHVzaC1mYWlsLnQ=..435375cc0ca085dea6a838a956a8eff1103828da_dGVzdHMvdGVzdC1tcS1xcHVzaC1mYWlsLnQ= 100644
--- a/tests/test-mq-qpush-fail.t
+++ b/tests/test-mq-qpush-fail.t
@@ -188,3 +188,52 @@
   bb
   $ cat c.orig
   cc
+
+test qpush --force and backup files
+
+  $ echo a >> a
+  $ hg qnew p2
+  $ echo b >> b
+  $ echo d > d
+  $ echo e > e
+  $ hg add d e
+  $ hg rm c
+  $ hg qnew p3
+  $ hg qpop -a
+  popping p3
+  popping p2
+  patch queue now empty
+  $ echo a >> a
+  $ echo b1 >> b
+  $ echo d1 > d
+  $ hg add d
+  $ echo e1 > e
+  $ hg qpush -a --force --verbose
+  applying p2
+  saving current version of a as a.orig
+  patching file a
+  a
+  applying p3
+  saving current version of b as b.orig
+  saving current version of d as d.orig
+  patching file b
+  patching file c
+  patching file d
+  file d already exists
+  1 out of 1 hunks FAILED -- saving rejects to file d.rej
+  patching file e
+  file e already exists
+  1 out of 1 hunks FAILED -- saving rejects to file e.rej
+  patch failed to apply
+  b
+  patch failed, rejects left in working dir
+  errors during apply, please fix and refresh p3
+  [2]
+  $ cat a.orig
+  a
+  a
+  $ cat b.orig
+  b
+  b1
+  $ cat d.orig
+  d1
diff --git a/tests/test-mq.t b/tests/test-mq.t
index b2ca2f40c9c1aa0e528381b3d10920915aaed527_dGVzdHMvdGVzdC1tcS50..435375cc0ca085dea6a838a956a8eff1103828da_dGVzdHMvdGVzdC1tcS50 100644
--- a/tests/test-mq.t
+++ b/tests/test-mq.t
@@ -1356,5 +1356,5 @@
 
 apply force, should discard changes in hello, but not bye
 
-  $ hg qpush -f
+  $ hg qpush -f --verbose
   applying empty
@@ -1360,4 +1360,7 @@
   applying empty
+  saving current version of hello.txt as hello.txt.orig
+  patching file hello.txt
+  hello.txt
   now at: empty
   $ hg st
   M bye.txt
@@ -1361,6 +1364,7 @@
   now at: empty
   $ hg st
   M bye.txt
+  ? hello.txt.orig
   $ hg diff --config diff.nodates=True
   diff -r ba252371dbc1 bye.txt
   --- a/bye.txt