diff --git a/rbtools/clients/svn.py b/rbtools/clients/svn.py
index af156e65267e271737bb66ab248d6739d0ab9d7c..8e065f67a50f2a0466874c1cb97aefc04556bc8d 100644
--- a/rbtools/clients/svn.py
+++ b/rbtools/clients/svn.py
@@ -24,6 +24,7 @@ class SVNClient(SCMClient):
     # Match the diff control lines generated by 'svn diff'.
     DIFF_ORIG_FILE_LINE_RE = re.compile(r'^---\s+.*\s+\(.*\)')
     DIFF_NEW_FILE_LINE_RE = re.compile(r'^\+\+\+\s+.*\s+\(.*\)')
+    DIFF_COMPLETE_REMOVAL_RE = re.compile(r'^@@ -1,\d+ \+0,0 @@$')
 
     REVISION_WORKING_COPY = '--rbtools-working-copy'
     REVISION_CHANGELIST_PREFIX = '--rbtools-changelist:'
@@ -211,7 +212,7 @@ class SVNClient(SCMClient):
 
         repository_info = self.get_repository_info()
 
-        diff_cmd = ['svn', 'diff', '--diff-cmd=diff']
+        diff_cmd = ['svn', 'diff', '--diff-cmd=diff', '--notice-ancestry']
         changelist = None
 
         if tip == self.REVISION_WORKING_COPY:
@@ -285,7 +286,7 @@ class SVNClient(SCMClient):
             status_cmd.extend(['--changelist', changelist])
 
         for p in execute(status_cmd, split_lines=True):
-            if p.startswith('A  +'):
+            if p[3] == '+':
                 return True
         return False
 
@@ -318,6 +319,10 @@ class SVNClient(SCMClient):
                 from_path1 = urllib.unquote(url[len(root):])
                 return smart_join(from_path1, path2)
 
+            if info.get('Schedule', None) != 'normal':
+                # Not added as a part of the parent directory, bail out
+                return None
+
             # Strip one component from path1 to path2
             path1, tmp = os.path.split(path1)
 
@@ -345,20 +350,37 @@ class SVNClient(SCMClient):
 
         result = []
 
-        from_line = ""
+        from_line = to_line = None
         for line in diff_content:
             if self.DIFF_ORIG_FILE_LINE_RE.match(line):
                 from_line = line
                 continue
 
-            # This is where we decide how mangle the previous '--- '
             if self.DIFF_NEW_FILE_LINE_RE.match(line):
-                to_file, _ = self.parse_filename_header(line[4:])
-                copied_from = self.find_copyfrom(to_file)
-                if copied_from is not None:
-                    result.append(from_line.replace(to_file, copied_from))
+                to_line = line
+                continue
+
+            # This is where we decide how mangle the previous '--- '
+            if from_line and to_line:
+                # If the file is marked completely removed, bail out with
+                # original diff. The reason for this is that 'svn diff
+                # --notice-ancestry' generates two diffs for a replaced file:
+                # one as a complete deletion, and one as a new addition.
+                # If it was replaced with history, though, we need to preserve
+                # the file name in the "deletion" part - or the patch won't
+                # apply.
+                if self.DIFF_COMPLETE_REMOVAL_RE.match(line):
+                    result.append(from_line)
+                    result.append(to_line)
                 else:
-                    result.append(from_line)  # As is, no copy performed
+                    to_file, _ = self.parse_filename_header(to_line[4:])
+                    copied_from = self.find_copyfrom(to_file)
+                    if copied_from is not None:
+                        result.append(from_line.replace(to_file, copied_from))
+                    else:
+                        result.append(from_line)  # As is, no copy performed
+                    result.append(to_line)
+                from_line = to_line = None
 
             # We only mangle '---' lines. All others get added straight to
             # the output.
