Index: src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 3334)
+++ src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(working copy)
@@ -561,7 +561,7 @@
 
     private static class Modified extends Match {
         @Override public boolean match(OsmPrimitive osm) {
-            return osm.isModified() || osm.isNew();
+            return osm.isModified() || osm.isNewOrUndeleted();
         }
         @Override public String toString() {return "modified";}
     }
Index: src/org/openstreetmap/josm/actions/UploadSelectionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 3334)
+++ src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(working copy)
@@ -77,9 +77,9 @@
     protected Set<OsmPrimitive> getModifiedPrimitives(Collection<OsmPrimitive> primitives) {
         HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
         for (OsmPrimitive p: primitives) {
-            if (p.isNew()) {
+            if (p.isNewOrUndeleted()) {
                 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.isNewOrUndeleted() || 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.isNewOrUndeleted() || w.isModified() || w.isDeleted()) {
                 // upload new ways as well as modified and deleted ones
                 hull.add(w);
                 for (Node n: w.getNodes()) {
@@ -205,14 +204,14 @@
         }
 
         public void visit(Relation r) {
-            if (r.isNew() || ((r.isModified() || r.isDeleted()) && r.isVisible())) {
+            if (r.isNewOrUndeleted() || r.isModified() || r.isDeleted()) {
                 hull.add(r);
                 for (OsmPrimitive p : r.getMemberPrimitives()) {
                     // add new relation members. Don't include modified
                     // relation members. r shouldn't refer to deleted primitives,
                     // so wont check here for deleted primitives here
                     //
-                    if (p.isNew()) {
+                    if (p.isNewOrUndeleted()) {
                         p.visit(this);
                     }
                 }
@@ -294,7 +293,7 @@
         protected Set<OsmPrimitive> getPrimitivesToCheckForParents() {
             HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
             for (OsmPrimitive p: toUpload) {
-                if (p.isDeleted() && !p.isNew()) {
+                if (p.isDeleted() && !p.isNewOrUndeleted()) {
                     ret.add(p);
                 }
             }
Index: src/org/openstreetmap/josm/actions/SaveActionBase.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 3334)
+++ src/org/openstreetmap/josm/actions/SaveActionBase.java	(working copy)
@@ -138,7 +138,7 @@
      */
     private boolean isDataSetEmpty(OsmDataLayer layer) {
         for (OsmPrimitive osm : layer.data.allNonDeletedPrimitives())
-            if (!osm.isDeleted() || !osm.isNew())
+            if (!osm.isDeleted() || !osm.isNewOrUndeleted())
                 return false;
         return true;
     }
Index: src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java	(revision 3334)
+++ src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java	(working copy)
@@ -47,7 +47,6 @@
 
 
     private ValidationListener validationListener = new ValidationListener() {
-        @Override
         public boolean validatePreferences() {
             if (sources.hasActiveStylesChanged()) {
                 List<String> sourcesToRemove = new ArrayList<String>();
Index: src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapStatus.java	(revision 3334)
+++ src/org/openstreetmap/josm/gui/MapStatus.java	(working copy)
@@ -419,7 +419,7 @@
         private final JLabel popupBuildPrimitiveLabels(final OsmPrimitive osm) {
             final StringBuilder text = new StringBuilder();
             String name = osm.getDisplayName(DefaultNameFormatter.getInstance());
-            if (osm.isNew() || osm.isModified()) {
+            if (osm.isNewOrUndeleted() || osm.isModified()) {
                 name = "<i><b>"+ name + "*</b></i>";
             }
             text.append(name);
Index: src/org/openstreetmap/josm/io/DiffResultProcessor.java
===================================================================
--- src/org/openstreetmap/josm/io/DiffResultProcessor.java	(revision 3334)
+++ 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 3334)
+++ 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 3334)
+++ 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.isNewOrUndeleted() || !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 3334)
+++ 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();
         }
     };
 
@@ -539,6 +547,16 @@
     }
 
     /**
+     *
+     * @return True if primitive is new or undeleted
+     * @see #isNew()
+     * @see #isUndeleted()
+     */
+    public boolean isNewOrUndeleted() {
+        return (id <= 0) || ((flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0);
+    }
+
+    /**
      * Sets the id and the version of this primitive if it is known to the OSM API.
      *
      * Since we know the id and its version it can't be incomplete anymore. incomplete
@@ -721,7 +739,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/osm/DatasetConsistencyTest.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DatasetConsistencyTest.java	(revision 3334)
+++ src/org/openstreetmap/josm/data/osm/DatasetConsistencyTest.java	(working copy)
@@ -126,7 +126,7 @@
 
     public void checkZeroNodesWays() {
         for (Way way:dataSet.getWays()) {
-            if (way.isUsable() && way.isVisible() && way.getNodesCount() == 0) {
+            if (way.isUsable() && way.getNodesCount() == 0) {
                 printError("WARN - ZERO NODES", "Way %s has zero nodes", way);
             } else if (way.isUsable() && way.getNodesCount() == 1) {
                 printError("WARN - NO NODES", "Way %s has only one node", way);
Index: src/org/openstreetmap/josm/data/osm/DataSetMerger.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 3334)
+++ src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(working copy)
@@ -188,14 +188,10 @@
         for (Node sourceNode : source.getNodes()) {
             Node targetNode = (Node)getMergeTarget(sourceNode);
             if (targetNode != null) {
-                if (targetNode.isVisible()) {
-                    newNodes.add(targetNode);
-                    if (targetNode.isDeleted() && !conflicts.hasConflictForMy(targetNode)) {
-                        conflicts.add(new Conflict<OsmPrimitive>(targetNode, sourceNode, true));
-                        targetNode.setDeleted(false);
-                    }
-                } else {
-                    target.setModified(true);
+                newNodes.add(targetNode);
+                if (targetNode.isDeleted() && !conflicts.hasConflictForMy(targetNode)) {
+                    conflicts.add(new Conflict<OsmPrimitive>(targetNode, sourceNode, true));
+                    targetNode.setDeleted(false);
                 }
             } else
                 throw new IllegalStateException(tr("Missing merge target for node with id {0}", sourceNode.getUniqueId()));
@@ -219,15 +215,11 @@
             OsmPrimitive targetMember = getMergeTarget(sourceMember.getMember());
             if (targetMember == null)
                 throw new IllegalStateException(tr("Missing merge target of type {0} with id {1}", sourceMember.getType(), sourceMember.getUniqueId()));
-            if (targetMember.isVisible()) {
-                RelationMember newMember = new RelationMember(sourceMember.getRole(), targetMember);
-                newMembers.add(newMember);
-                if (targetMember.isDeleted() && !conflicts.hasConflictForMy(targetMember)) {
-                    conflicts.add(new Conflict<OsmPrimitive>(targetMember, sourceMember.getMember(), true));
-                    targetMember.setDeleted(false);
-                }
-            } else {
-                target.setModified(true);
+            RelationMember newMember = new RelationMember(sourceMember.getRole(), targetMember);
+            newMembers.add(newMember);
+            if (targetMember.isDeleted() && !conflicts.hasConflictForMy(targetMember)) {
+                conflicts.add(new Conflict<OsmPrimitive>(targetMember, sourceMember.getMember(), true));
+                targetMember.setDeleted(false);
             }
         }
         target.setMembers(newMembers);
@@ -251,15 +243,9 @@
         if (target.getVersion() > source.getVersion())
             // target.version > source.version => keep target version
             return true;
-        if (! target.isVisible() && source.isVisible()) {
+        if (! target.isVisible() && source.isVisible() && target.getVersion() == source.getVersion()) {
             // should not happen
-            // FIXME: this message does not make sense, source version can not be lower than
-            //        target version at this point
-            logger.warning(tr("Target object with id {0} and version {1} is visible although "
-                    + "source object with lower version {2} is not visible. "
-                    + "Cannot deal with this inconsistency. Keeping target object. ",
-                    Long.toString(target.getId()),Long.toString(target.getVersion()), Long.toString(source.getVersion())
-            ));
+            conflicts.add(target,source);
         } else if (target.isVisible() && ! source.isVisible()) {
             // this is always a conflict because the user has to decide whether
             // he wants to create a clone of its target primitive or whether he
Index: src/org/openstreetmap/josm/data/APIDataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/APIDataSet.java	(revision 3334)
+++ src/org/openstreetmap/josm/data/APIDataSet.java	(working copy)
@@ -60,11 +60,11 @@
             if (osm.get("josm/ignore") != null) {
                 continue;
             }
-            if (osm.isNew() && !osm.isDeleted()) {
+            if (osm.isNewOrUndeleted() && !osm.isDeleted()) {
                 toAdd.add(osm);
             } else if (osm.isModified() && !osm.isDeleted()) {
                 toUpdate.add(osm);
-            } else if (osm.isDeleted() && !osm.isNew() && osm.isModified()) {
+            } else if (osm.isDeleted() && !osm.isNew() && osm.isModified() && osm.isVisible()) {
                 toDelete.add(osm);
             }
         }
@@ -197,11 +197,11 @@
         toUpdate.clear();
         toDelete.clear();
         for (OsmPrimitive osm: primitives) {
-            if (osm.isNew() && !osm.isDeleted()) {
+            if (osm.isNewOrUndeleted() && !osm.isDeleted()) {
                 toAdd.addLast(osm);
             } else if (osm.isModified() && !osm.isDeleted()) {
                 toUpdate.addLast(osm);
-            } else if (osm.isDeleted() && !osm.isNew() && osm.isModified()) {
+            } else if (osm.isDeleted() && !osm.isNew() && osm.isModified() && osm.isVisible()) {
                 toDelete.addFirst(osm);
             }
         }
@@ -311,7 +311,7 @@
         for (Relation relation: relations) {
             boolean refersToNewRelation = false;
             for (RelationMember m : relation.getMembers()) {
-                if (m.isRelation() && m.getMember().isNew()) {
+                if (m.isRelation() && m.getMember().isNewOrUndeleted()) {
                     refersToNewRelation = true;
                     break;
                 }
@@ -349,12 +349,12 @@
         public void build(Collection<Relation> relations) {
             this.relations = new HashSet<Relation>();
             for(Relation relation: relations) {
-                if (!relation.isNew() ) {
+                if (!relation.isNewOrUndeleted() ) {
                     continue;
                 }
                 this.relations.add(relation);
                 for (RelationMember m: relation.getMembers()) {
-                    if (m.isRelation() && m.getMember().isNew()) {
+                    if (m.isRelation() && m.getMember().isNewOrUndeleted()) {
                         addDependency(relation, (Relation)m.getMember());
                     }
                 }
Index: src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 3334)
+++ src/org/openstreetmap/josm/command/DeleteCommand.java	(working copy)
@@ -444,7 +444,7 @@
             for (OsmPrimitive osm : primitivesToDelete) {
                 if (osm.isIncomplete())
                     incomplete = true;
-                else if (osm instanceof Node && !osm.isNew()
+                else if (osm instanceof Node && !osm.isNewOrUndeleted()
                 && !a.contains(((Node) osm).getCoor()))
                     outside = true;
             }
