Index: src/org/openstreetmap/josm/actions/UploadSelectionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 3331)
+++ src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(working copy)
@@ -79,7 +79,7 @@
         for (OsmPrimitive p: primitives) {
             if (p.isNew()) {
                 ret.add(p);
-            } else if (p.isVisible() && p.isModified() && !p.isIncomplete()) {
+            } else if (p.isModified() && !p.isIncomplete()) {
                 ret.add(p);
             }
         }
@@ -170,8 +170,7 @@
     /**
      * Computes the collection of primitives to upload, given a collection of candidate
      * primitives.
-     * Some of the candidates are excluded, i.e. if they aren't modified or if they
-     * aren't visible.
+     * Some of the candidates are excluded, i.e. if they aren't modified.
      * Other primitives are added. A typical case is a primitive which is new and and
      * which is referred by a modified relation. In order to upload the relation the
      * new primitive has to be uploaded as well, even if it isn't included in the
@@ -186,14 +185,14 @@
         }
 
         public void visit(Node n) {
-            if (n.isNew() || ((n.isModified() || n.isDeleted()) && n.isVisible())) {
+            if (n.isNew() || n.isModified() || n.isDeleted()) {
                 // upload new nodes as well as modified and deleted ones
                 hull.add(n);
             }
         }
 
         public void visit(Way w) {
-            if (w.isNew() || ((w.isModified() || w.isDeleted()) && w.isVisible())) {
+            if (w.isNew() || w.isModified() || w.isDeleted()) {
                 // upload new ways as well as modified and deleted ones
                 hull.add(w);
                 for (Node n: w.getNodes()) {
@@ -205,7 +204,7 @@
         }
 
         public void visit(Relation r) {
-            if (r.isNew() || ((r.isModified() || r.isDeleted()) && r.isVisible())) {
+            if (r.isNew() || r.isModified() || r.isDeleted()) {
                 hull.add(r);
                 for (OsmPrimitive p : r.getMemberPrimitives()) {
                     // add new relation members. Don't include modified
Index: src/org/openstreetmap/josm/io/DiffResultProcessor.java
===================================================================
--- src/org/openstreetmap/josm/io/DiffResultProcessor.java	(revision 3331)
+++ src/org/openstreetmap/josm/io/DiffResultProcessor.java	(working copy)
@@ -124,6 +124,7 @@
                 processed.add(p);
                 if (!p.isDeleted()) {
                     p.setOsmId(entry.new_id, entry.new_version);
+                    p.setVisible(true);
                 }
                 if (cs != null && !cs.isNew()) {
                     p.setChangesetId(cs.getId());
Index: src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmApi.java	(revision 3331)
+++ src/org/openstreetmap/josm/io/OsmApi.java	(working copy)
@@ -274,6 +274,7 @@
             ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.getId(), toXml(osm, true), monitor);
             osm.setOsmId(osm.getId(), Integer.parseInt(ret.trim()));
             osm.setChangesetId(getChangeset().getId());
+            osm.setVisible(true);
         } catch(NumberFormatException e) {
             throw new OsmTransferException(tr("Unexpected format of new version of modified primitive ''{0}''. Got ''{1}''.", osm.getId(), ret));
         }
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 3331)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(working copy)
@@ -97,7 +97,7 @@
     }
 
     private boolean shouldWrite(OsmPrimitive osm) {
-        return !osm.isNew() || !osm.isDeleted();
+        return (!osm.isNew() && osm.isVisible()) || !osm.isDeleted();
     }
 
     public void writeDataSources(DataSet ds) {
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 3331)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(working copy)
@@ -391,6 +391,14 @@
     }
 
     /**
+     * Replies <code>true</code> if the object has been deleted on the server and was undeleted by the user.
+     * @return <code>true</code> if the object has been undeleted
+     */
+    public boolean isUndeleted() {
+        return (flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0;
+    }
+
+    /**
      * Replies <code>true</code>, if the object is usable (i.e. complete
      * and not deleted).
      *
@@ -426,25 +434,25 @@
 
     public static Predicate<OsmPrimitive> nonDeletedPredicate = new Predicate<OsmPrimitive>() {
         public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isVisible() && !primitive.isDeleted();
+            return !primitive.isDeleted();
         }
     };
 
     public static Predicate<OsmPrimitive> nonDeletedCompletePredicate = new Predicate<OsmPrimitive>() {
         public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isVisible() && !primitive.isDeleted() && !primitive.isIncomplete();
+            return !primitive.isDeleted() && !primitive.isIncomplete();
         }
     };
 
     public static Predicate<OsmPrimitive> nonDeletedPhysicalPredicate = new Predicate<OsmPrimitive>() {
         public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isVisible() && !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation);
+            return !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation);
         }
     };
 
     public static Predicate<OsmPrimitive> modifiedPredicate = new Predicate<OsmPrimitive>() {
         public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isVisible() && primitive.isModified();
+            return primitive.isModified();
         }
     };
 
@@ -721,7 +729,7 @@
         } else {
             flags &= ~FLAG_DELETED;
         }
-        setModified(deleted);
+        setModified(deleted ^ !isVisible());
         if (dataSet != null) {
             if (deleted) {
                 dataSet.firePrimitivesRemoved(Collections.singleton(this), false);
Index: src/org/openstreetmap/josm/data/APIDataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/APIDataSet.java	(revision 3331)
+++ src/org/openstreetmap/josm/data/APIDataSet.java	(working copy)
@@ -56,6 +56,7 @@
         toUpdate.clear();
         toDelete.clear();
 
+        boolean sortUpdated = false;
         for (OsmPrimitive osm :ds.allPrimitives()) {
             if (osm.get("josm/ignore") != null) {
                 continue;
@@ -63,6 +64,9 @@
             if (osm.isNew() && !osm.isDeleted()) {
                 toAdd.add(osm);
             } else if (osm.isModified() && !osm.isDeleted()) {
+                if (osm.isUndeleted()) {
+                    sortUpdated = true;
+                }
                 toUpdate.add(osm);
             } else if (osm.isDeleted() && !osm.isNew() && osm.isModified()) {
                 toDelete.add(osm);
@@ -70,6 +74,9 @@
         }
         sortDeleted();
         sortNew();
+        if (sortUpdated) {
+            sortUpdated();
+        }
     }
 
     /**
@@ -131,7 +138,38 @@
                 }
         );
     }
+
     /**
+     * Ensures that primitives are modified in the following order: Nodes, then Ways,
+     * then Relations. It's necessary for uploading undeleted objects.
+     *
+     */
+    protected void sortUpdated() {
+        Collections.sort(
+                toUpdate,
+                new Comparator<OsmPrimitive>() {
+                    public int compare(OsmPrimitive o1, OsmPrimitive o2) {
+                        if (o1 instanceof Node && o2 instanceof Node)
+                            return 0;
+                        else if (o1 instanceof Node)
+                            return -1;
+                        else if (o2 instanceof Node)
+                            return 1;
+
+                        if (o1 instanceof Way && o2 instanceof Way)
+                            return 0;
+                        else if (o1 instanceof Way && o2 instanceof Relation)
+                            return -1;
+                        else if (o2 instanceof Way && o1 instanceof Relation)
+                            return 1;
+
+                        return 0;
+                    }
+                }
+        );
+    }
+
+    /**
      * initializes the API data set with the modified primitives in <code>ds</code>
      *
      * @param ds the data set. Ignored, if null.
@@ -196,17 +234,25 @@
         toAdd.clear();
         toUpdate.clear();
         toDelete.clear();
+
+        boolean sortUpdated = false;
         for (OsmPrimitive osm: primitives) {
             if (osm.isNew() && !osm.isDeleted()) {
                 toAdd.addLast(osm);
             } else if (osm.isModified() && !osm.isDeleted()) {
                 toUpdate.addLast(osm);
+                if (osm.isUndeleted()) {
+                    sortUpdated = true;
+                }
             } else if (osm.isDeleted() && !osm.isNew() && osm.isModified()) {
                 toDelete.addFirst(osm);
             }
         }
         sortNew();
         sortDeleted();
+        if (sortUpdated) {
+            sortUpdated();
+        }
     }
 
     /**
