Index: src/org/openstreetmap/josm/data/osm/DataSetMerger.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 17274)
+++ src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(working copy)
@@ -297,6 +297,7 @@
         // found a corresponding target, remember it
         mergedMap.put(source.getPrimitiveId(), target.getPrimitiveId());
 
+        boolean mergeFromSource = false;
         if (target.getVersion() > source.getVersion())
             // target.version > source.version => keep target version
             return true;
@@ -305,8 +306,7 @@
             // target is incomplete, source completes it
             // => merge source into target
             //
-            target.mergeFrom(source);
-            objectsWithChildrenToMerge.add(source.getPrimitiveId());
+            mergeFromSource = true;
         } else if (!target.isIncomplete() && source.isIncomplete()) {
             // target is complete and source is incomplete
             // => keep target, it has more information already
@@ -323,6 +323,9 @@
             // We shouldn't merge that datasets.
             throw new DataIntegrityProblemException(tr("Conflict in ''visible'' attribute for object of type {0} with id {1}",
                     target.getType(), target.getId()));
+        } else if (target.isDeleted() && source.isDeleted() && target.getVersion() < source.getVersion()) {
+            // both deleted. Source is newer. Take source. See #19783
+            mergeFromSource = true;
         } else if (target.isDeleted() && !source.isDeleted() && target.getVersion() == source.getVersion()) {
             // same version, but target is deleted. Assume target takes precedence
             // otherwise too many conflicts when refreshing from the server
@@ -347,18 +350,15 @@
         } else if (!target.isModified() && source.isModified()) {
             // target not modified. We can assume that source is the most recent version.
             // clone it into target.
-            target.mergeFrom(source);
-            objectsWithChildrenToMerge.add(source.getPrimitiveId());
+            mergeFromSource = true;
         } else if (!target.isModified() && !source.isModified() && target.getVersion() == source.getVersion()) {
             // both not modified. Merge nevertheless.
             // This helps when updating "empty" relations, see #4295
-            target.mergeFrom(source);
-            objectsWithChildrenToMerge.add(source.getPrimitiveId());
+            mergeFromSource = true;
         } else if (!target.isModified() && !source.isModified() && target.getVersion() < source.getVersion()) {
             // my not modified but other is newer. clone other onto mine.
             //
-            target.mergeFrom(source);
-            objectsWithChildrenToMerge.add(source.getPrimitiveId());
+            mergeFromSource = true;
         } else if (target.isModified() && !source.isModified() && target.getVersion() == source.getVersion()) {
             // target is same as source but target is modified
             // => keep target and reset modified flag if target and source are semantically equal
@@ -380,6 +380,9 @@
             // technical attributes like timestamp or user information. Semantic
             // attributes should already be equal if we get here.
             //
+            mergeFromSource = true;
+        }
+        if (mergeFromSource) {
             target.mergeFrom(source);
             objectsWithChildrenToMerge.add(source.getPrimitiveId());
         }
