Index: test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java	(revision 3339)
+++ test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java	(working copy)
@@ -233,38 +233,6 @@
     }
 
     /**
-     * My node is visible, their version has a higher version and is not visible
-     * => create a conflict
-     *
-     */
-    @Test
-    public void nodeSimple_VisibleConflict() {
-        Node n = new Node(new LatLon(0,0));
-        n.setOsmId(1,1);
-        n.setModified(false);
-        n.setVisible(true);
-        my.addPrimitive(n);
-
-        Node n1 = new Node(new LatLon(0,0));
-        n1.setOsmId(1,2);
-
-        n1.setModified(false);
-        n1.setVisible(false);
-        their.addPrimitive(n1);
-
-
-        DataSetMerger visitor = new DataSetMerger(my,their);
-        visitor.merge();
-
-        Node n2 = (Node)my.getPrimitiveById(1,OsmPrimitiveType.NODE);
-        assertEquals(1,visitor.getConflicts().size());
-        assertEquals(true, n2.isVisible());
-        assertTrue(n == n2);
-        assertTrue(n1 != n2);
-        assertTrue(n1.getDataSet() == their);
-    }
-
-    /**
      * My node is deleted, their node has the same id and version and is not deleted.
      * => mine has precedence
      *
@@ -342,34 +310,6 @@
     }
 
     /**
-     * their node is not visible and doesn't exist in my data set
-     * => we can't ignore it because we'd run into troubles in case of multi fetch
-     * which can return invisible objects
-     *
-     */
-    @Test
-    public void nodeSimple_InvisibleNodeInTheirDataset() {
-        Node n = new Node(new LatLon(0,0));
-        n.setOsmId(1,1);
-        n.setDeleted(true);
-        my.addPrimitive(n);
-
-        Node n1 = new Node(new LatLon(0,0));
-        n1.setOsmId(2,1);
-        n1.setVisible(false);
-        their.addPrimitive(n1);
-
-
-        DataSetMerger visitor = new DataSetMerger(my,their);
-        visitor.merge();
-
-        Node n2 = (Node)my.getPrimitiveById(1,OsmPrimitiveType.NODE);
-        assertEquals(0,visitor.getConflicts().size());
-        assertEquals(2, my.getNodes().size());
-        assertEquals(n,n2);
-    }
-
-    /**
      * their node has no assigned id (id == 0) and is semantically equal to one of my
      * nodes with id == 0
      *
@@ -687,6 +627,10 @@
         Way theirWay = new Way();
         theirWay.setOsmId(3,2);
         theirWay.setVisible(false);
+        /* Invisible objects fetched from the server should be marked as "deleted".
+         * Otherwise it's an error.
+         */
+        theirWay.setDeleted(true);
         their.addPrimitive(theirWay);
 
         DataSetMerger visitor = new DataSetMerger(my,their);
Index: src/org/openstreetmap/josm/gui/conflict/pair/ConflictResolver.java
===================================================================
--- src/org/openstreetmap/josm/gui/conflict/pair/ConflictResolver.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/conflict/pair/ConflictResolver.java	(working copy)
@@ -25,7 +25,6 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.conflict.pair.nodes.NodeListMergeModel;
 import org.openstreetmap.josm.gui.conflict.pair.nodes.NodeListMerger;
-import org.openstreetmap.josm.gui.conflict.pair.properties.OperationCancelledException;
 import org.openstreetmap.josm.gui.conflict.pair.properties.PropertiesMergeModel;
 import org.openstreetmap.josm.gui.conflict.pair.properties.PropertiesMerger;
 import org.openstreetmap.josm.gui.conflict.pair.relation.RelationMemberListMergeModel;
@@ -234,12 +233,7 @@
         setTheir(conflict.getTheir());
         this.conflict = conflict;
         propertiesMerger.populate(conflict);
-        if (propertiesMerger.getModel().hasVisibleStateConflict()) {
-            tabbedPane.setEnabledAt(1, false);
-            tabbedPane.setEnabledAt(2, false);
-            tabbedPane.setEnabledAt(3, false);
-            return;
-        }
+
         tabbedPane.setEnabledAt(0, true);
         tagMerger.populate(conflict);
         tabbedPane.setEnabledAt(1, true);
@@ -269,29 +263,24 @@
      *
      * @return the resolution command
      */
-    public Command buildResolveCommand() throws OperationCancelledException {
+    public Command buildResolveCommand() {
         ArrayList<Command> commands = new ArrayList<Command>();
-        if (propertiesMerger.getModel().hasVisibleStateConflict()) {
-            if (propertiesMerger.getModel().isDecidedVisibleState()) {
-                commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
-            }
-        } else {
-            if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
-                commands.add(tagMerger.getModel().buildResolveCommand(conflict));
-            }
-            commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
-            if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
-                NodeListMergeModel model  =(NodeListMergeModel)nodeListMerger.getModel();
-                commands.add(model.buildResolveCommand(conflict));
-            } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
-                RelationMemberListMergeModel model  =(RelationMemberListMergeModel)relationMemberMerger.getModel();
-                commands.add(model.buildResolveCommand((Relation)my, (Relation)their));
-            }
-            if (isResolvedCompletely()) {
-                commands.add(new VersionConflictResolveCommand(conflict));
-                commands.add(new ModifiedConflictResolveCommand(conflict));
-            }
+
+        if (tagMerger.getModel().getNumResolvedConflicts() > 0) {
+            commands.add(tagMerger.getModel().buildResolveCommand(conflict));
         }
+        commands.addAll(propertiesMerger.getModel().buildResolveCommand(conflict));
+        if (my instanceof Way && nodeListMerger.getModel().isFrozen()) {
+            NodeListMergeModel model = (NodeListMergeModel) nodeListMerger.getModel();
+            commands.add(model.buildResolveCommand(conflict));
+        } else if (my instanceof Relation && relationMemberMerger.getModel().isFrozen()) {
+            RelationMemberListMergeModel model = (RelationMemberListMergeModel) relationMemberMerger.getModel();
+            commands.add(model.buildResolveCommand((Relation) my, (Relation) their));
+        }
+        if (isResolvedCompletely()) {
+            commands.add(new VersionConflictResolveCommand(conflict));
+            commands.add(new ModifiedConflictResolveCommand(conflict));
+        }
         return new SequenceCommand(tr("Conflict Resolution"), commands);
     }
 
Index: src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergeModel.java
===================================================================
--- src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergeModel.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMergeModel.java	(working copy)
@@ -2,37 +2,22 @@
 package org.openstreetmap.josm.gui.conflict.pair.properties;
 
 import static org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType.UNDECIDED;
-import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Observable;
 
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.CoordinateConflictResolveCommand;
 import org.openstreetmap.josm.command.DeletedStateConflictResolveCommand;
-import org.openstreetmap.josm.command.PurgePrimitivesCommand;
-import org.openstreetmap.josm.command.UndeletePrimitivesCommand;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType;
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
-import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
-import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
@@ -64,12 +49,9 @@
 
     private boolean myDeletedState;
     private boolean theirDeletedState;
-    private boolean myVisibleState;
-    private boolean theirVisibleState;
     private List<OsmPrimitive> myReferrers;
     private List<OsmPrimitive> theirReferrers;
     private MergeDecisionType deletedMergeDecision;
-    private MergeDecisionType visibleMergeDecision;
     private final PropertyChangeSupport support;
     private boolean resolvedCompletely;
 
@@ -117,17 +99,6 @@
     }
 
     /**
-     * replies true if there is a  conflict in the visible state and if this conflict is
-     * resolved
-     *
-     * @return true if there is a conflict in the visible state and if this conflict is
-     * resolved; false, otherwise
-     */
-    public boolean isDecidedVisibleState() {
-        return ! visibleMergeDecision.equals(UNDECIDED);
-    }
-
-    /**
      * replies true if the current decision for the coordinate conflict is <code>decision</code>
      *
      * @return true if the current decision for the coordinate conflict is <code>decision</code>;
@@ -148,15 +119,6 @@
     }
 
     /**
-     * replies true if the current decision for the visible state conflict is <code>decision</code>
-     *
-     * @return true if the current decision for the visible state conflict is <code>decision</code>;
-     *  false, otherwise
-     */
-    public boolean isVisibleStateDecision(MergeDecisionType decision) {
-        return visibleMergeDecision.equals(decision);
-    }
-    /**
      * populates the model with the differences between my and their version
      *
      * @param my my version of the primitive
@@ -176,15 +138,11 @@
         myDeletedState =  conflict.isMyDeleted() || my.isDeleted();
         theirDeletedState = their.isDeleted();
 
-        myVisibleState = my.isVisible();
-        theirVisibleState = their.isVisible();
-
         myReferrers = my.getDataSet() == null?Collections.<OsmPrimitive>emptyList():my.getReferrers();
         theirReferrers = their.getDataSet() == null?Collections.<OsmPrimitive>emptyList():their.getReferrers();
 
         coordMergeDecision = UNDECIDED;
         deletedMergeDecision = UNDECIDED;
-        visibleMergeDecision = UNDECIDED;
         setChanged();
         notifyObservers();
         fireCompletelyResolved();
@@ -264,22 +222,6 @@
     }
 
     /**
-     * replies my visible state,
-     * @return my visible state
-     */
-    public Boolean getMyVisibleState() {
-        return myVisibleState;
-    }
-
-    /**
-     * replies their visible state,
-     * @return their visible state
-     */
-    public  Boolean getTheirVisibleState() {
-        return theirVisibleState;
-    }
-
-    /**
      * returns my referrers,
      * @return my referrers
      */
@@ -295,22 +237,6 @@
         return theirReferrers;
     }
 
-    /**
-     * replies the merged visible state; null, if the merge decision is
-     * {@see MergeDecisionType#UNDECIDED}.
-     *
-     * @return the merged visible state
-     */
-    public Boolean getMergedVisibleState() {
-        switch(visibleMergeDecision) {
-        case KEEP_MINE: return myVisibleState;
-        case KEEP_THEIR: return theirVisibleState;
-        case UNDECIDED: return null;
-        }
-        // should not happen
-        return null;
-    }
-
     private boolean getMergedDeletedState(MergeDecisionType decision) {
         switch (decision) {
         case KEEP_MINE:
@@ -345,20 +271,6 @@
     }
 
     /**
-     * decides the conflict between two visible states
-     * @param decision the decision (must not be null)
-     *
-     * @throws IllegalArgumentException thrown, if decision is null
-     */
-    public void decideVisibleStateConflict(MergeDecisionType decision) throws IllegalArgumentException {
-        CheckParameterUtil.ensureParameterNotNull(decision, "decision");
-        this.visibleMergeDecision = decision;
-        setChanged();
-        notifyObservers();
-        fireCompletelyResolved();
-    }
-
-    /**
      * replies true if my and their primitive have a conflict between
      * their coordinate values
      *
@@ -384,17 +296,6 @@
     }
 
     /**
-     * replies true if my and their primitive have a conflict between
-     * their visible states
-     *
-     * @return true if my and their primitive have a conflict between
-     * their visible states
-     */
-    public boolean hasVisibleStateConflict() {
-        return myVisibleState != theirVisibleState;
-    }
-
-    /**
      * replies true if all conflict in this model are resolved
      *
      * @return true if all conflict in this model are resolved; false otherwise
@@ -407,9 +308,6 @@
         if (hasDeletedStateConflict()) {
             ret = ret && ! deletedMergeDecision.equals(UNDECIDED);
         }
-        if (hasVisibleStateConflict()) {
-            ret = ret && ! visibleMergeDecision.equals(UNDECIDED);
-        }
         return ret;
     }
 
@@ -420,24 +318,8 @@
      * @param their their primitive
      * @return the list of commands
      */
-    public List<Command> buildResolveCommand(Conflict<? extends OsmPrimitive> conflict) throws OperationCancelledException{
-        OsmPrimitive my = conflict.getMy();
+    public List<Command> buildResolveCommand(Conflict<? extends OsmPrimitive> conflict) {
         List<Command> cmds = new ArrayList<Command>();
-        if (hasVisibleStateConflict() && isDecidedVisibleState()) {
-            if (isVisibleStateDecision(MergeDecisionType.KEEP_MINE)) {
-                try {
-                    UndeletePrimitivesCommand cmd = createUndeletePrimitiveCommand(my);
-                    if (cmd == null)
-                        throw new OperationCancelledException();
-                    cmds.add(cmd);
-                } catch(OsmTransferException e) {
-                    handleExceptionWhileBuildingCommand(e);
-                    throw new OperationCancelledException(e);
-                }
-            } else if (isVisibleStateDecision(MergeDecisionType.KEEP_THEIR)) {
-                cmds.add(new PurgePrimitivesCommand(my));
-            }
-        }
         if (hasCoordConflict() && isDecidedCoord()) {
             cmds.add(new CoordinateConflictResolveCommand(conflict, coordMergeDecision));
         }
@@ -451,201 +333,4 @@
         return my;
     }
 
-    /**
-     *
-     * @param id
-     */
-    protected void handleExceptionWhileBuildingCommand(Exception e) {
-        e.printStackTrace();
-        String msg = e.getMessage() != null ? e.getMessage() : e.toString();
-        msg = msg.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
-        JOptionPane.showMessageDialog(
-                Main.parent,
-                tr("<html>An error occurred while communicating with the server<br>"
-                        + "Details: {0}</html>",
-                        msg
-                ),
-                tr("Communication with server failed"),
-                JOptionPane.ERROR_MESSAGE
-        );
-    }
-
-    /**
-     * User has decided to keep his local version of a primitive which had been deleted
-     * on the server
-     *
-     * @param id the primitive id
-     */
-    protected UndeletePrimitivesCommand createUndeletePrimitiveCommand(OsmPrimitive my) throws OsmTransferException {
-        if (my instanceof Node)
-            return createUndeleteNodeCommand((Node)my);
-        else if (my instanceof Way)
-            return createUndeleteWayCommand((Way)my);
-        else if (my instanceof Relation)
-            return createUndeleteRelationCommand((Relation)my);
-        return null;
-    }
-    /**
-     * Undelete a node which is already deleted on the server. The API
-     * doesn't offer a call for "undeleting" a node. We therefore create
-     * a clone of the node which we flag as new. On the next upload the
-     * server will assign the node a new id.
-     *
-     * @param node the node to undelete
-     */
-    protected UndeletePrimitivesCommand  createUndeleteNodeCommand(Node node) {
-        return new UndeletePrimitivesCommand(node);
-    }
-
-    /**
-     * displays a confirmation message. The user has to confirm that additional dependent
-     * nodes should be undeleted too.
-     *
-     * @param way  the way
-     * @param dependent a list of dependent nodes which have to be undelete too
-     * @return true, if the user confirms; false, otherwise
-     */
-    protected boolean confirmUndeleteDependentPrimitives(Way way, ArrayList<OsmPrimitive> dependent) {
-        String [] options = {
-                tr("Yes, undelete them too"),
-                tr("No, cancel operation")
-        };
-        int ret = JOptionPane.showOptionDialog(
-                Main.parent,
-                "<html>" + trn("There is {0} additional node used by way {1}<br>"
-                        + "which is deleted on the server."
-                        + "<br><br>"
-                        + "Do you want to undelete this node too?",
-                        "There are {0} additional nodes used by way {1}<br>"
-                        + "which are deleted on the server."
-                        + "<br><br>"
-                        + "Do you want to undelete these nodes too?",
-                        dependent.size(), dependent.size(), way.getId())
-                        + "</html>",
-                        tr("Undelete additional nodes?"),
-                        JOptionPane.YES_NO_OPTION,
-                        JOptionPane.QUESTION_MESSAGE,
-                        null,
-                        options,
-                        options[0]
-        );
-
-        switch(ret) {
-        case JOptionPane.CLOSED_OPTION: return false;
-        case JOptionPane.YES_OPTION: return true;
-        case JOptionPane.NO_OPTION: return false;
-        }
-        return false;
-
-    }
-
-    protected boolean confirmUndeleteDependentPrimitives(Relation r, ArrayList<OsmPrimitive> dependent) {
-        String [] options = {
-                tr("Yes, undelete them too"),
-                tr("No, cancel operation")
-        };
-        int ret = JOptionPane.showOptionDialog(
-                Main.parent,
-                "<html>" + trn("There is {0} additional primitive referred to by relation {1}<br>"
-                        + "which is deleted on the server."
-                        + "<br><br>"
-                        + "Do you want to undelete this too?",
-                        "There are {0} additional primitives referred to by relation {1}<br>"
-                        + "which are deleted on the server."
-                        + "<br><br>"
-                        + "Do you want to undelete these too?",
-                        dependent.size(), dependent.size(), r.getId())
-                        + "</html>",
-                        tr("Undelete dependent primitives?"),
-                        JOptionPane.YES_NO_OPTION,
-                        JOptionPane.QUESTION_MESSAGE,
-                        null,
-                        options,
-                        options[0]
-        );
-
-        switch(ret) {
-        case JOptionPane.CLOSED_OPTION: return false;
-        case JOptionPane.YES_OPTION: return true;
-        case JOptionPane.NO_OPTION: return false;
-        }
-        return false;
-
-    }
-
-    /**
-     * Creates the undelete command for a way which is already deleted on the server.
-     *
-     * This method also checks whether there are additional nodes referred to by
-     * this way which are deleted on the server too.
-     *
-     * @param way the way to undelete
-     * @return the undelete command
-     * @see #createUndeleteNodeCommand(Node)
-     */
-    protected UndeletePrimitivesCommand createUndeleteWayCommand(final Way way) throws OsmTransferException {
-
-        HashMap<Long,OsmPrimitive> candidates = new HashMap<Long,OsmPrimitive>();
-        for (Node n : way.getNodes()) {
-            if (!n.isNew() && !candidates.values().contains(n)) {
-                candidates.put(n.getId(), n);
-            }
-        }
-        MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
-        reader.append(candidates.values());
-        DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
-
-        ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
-        for (OsmPrimitive their : ds.allPrimitives()) {
-            if (candidates.keySet().contains(their.getId()) && ! their.isVisible()) {
-                toDelete.add(candidates.get(their.getId()));
-            }
-        }
-        if (!toDelete.isEmpty()) {
-            if (! confirmUndeleteDependentPrimitives(way, toDelete))
-                // FIXME: throw exception ?
-                return null;
-        }
-        toDelete.add(way);
-        return new UndeletePrimitivesCommand(toDelete);
-    }
-
-    /**
-     * Creates an undelete command for a relation which is already deleted on the server.
-     *
-     * This method  checks whether there are additional primitives referred to by
-     * this relation which are already deleted on the server.
-     *
-     * @param r the relation
-     * @return the undelete command
-     * @see #createUndeleteNodeCommand(Node)
-     */
-    protected UndeletePrimitivesCommand createUndeleteRelationCommand(final Relation r) throws OsmTransferException {
-
-        HashMap<Long,OsmPrimitive> candidates = new HashMap<Long, OsmPrimitive>();
-        for (RelationMember m : r.getMembers()) {
-            if (!m.getMember().isNew() && !candidates.values().contains(m.getMember())) {
-                candidates.put(m.getMember().getId(), m.getMember());
-            }
-        }
-
-        MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
-        reader.append(candidates.values());
-        DataSet ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
-
-        ArrayList<OsmPrimitive> toDelete = new ArrayList<OsmPrimitive>();
-        for (OsmPrimitive their : ds.allPrimitives()) {
-            if (candidates.keySet().contains(their.getId()) && ! their.isVisible()) {
-                toDelete.add(candidates.get(their.getId()));
-            }
-        }
-        if (!toDelete.isEmpty()) {
-            if (! confirmUndeleteDependentPrimitives(r, toDelete))
-                // FIXME: throw exception ?
-                return null;
-        }
-        toDelete.add(r);
-        return new UndeletePrimitivesCommand(toDelete);
-    }
-
 }
Index: src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMerger.java
===================================================================
--- src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMerger.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMerger.java	(working copy)
@@ -18,7 +18,6 @@
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 
 import org.openstreetmap.josm.data.conflict.Conflict;
@@ -53,10 +52,6 @@
     private JLabel lblMergedDeletedState;
     private JLabel lblTheirDeletedState;
 
-    private JLabel lblMyVisibleState;
-    private JLabel lblMergedVisibleState;
-    private JLabel lblTheirVisibleState;
-
     private JLabel lblMyReferrers;
     private JLabel lblTheirReferrers;
 
@@ -250,82 +245,6 @@
         add(btnUndecideDeletedState, gc);
     }
 
-    protected void buildVisibleStateRows() {
-        GridBagConstraints gc = new GridBagConstraints();
-
-        gc.gridx = 0;
-        gc.gridy = 5;
-        gc.gridwidth = 1;
-        gc.gridheight = 1;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.anchor = GridBagConstraints.LINE_START;
-        gc.weightx = 0.0;
-        gc.weighty = 0.0;
-        gc.insets = new Insets(0,5,0,5);
-        add(new JLabel(tr("Visible State:")), gc);
-
-        gc.gridx = 1;
-        gc.gridy = 5;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.33;
-        gc.weighty = 0.0;
-        add(lblMyVisibleState = buildValueLabel("label.myvisiblestate"), gc);
-
-        gc.gridx = 2;
-        gc.gridy = 5;
-        gc.fill = GridBagConstraints.NONE;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.0;
-        gc.weighty = 0.0;
-        KeepMyVisibleStateAction actKeepMyVisibleState = new KeepMyVisibleStateAction();
-        model.addObserver(actKeepMyVisibleState);
-        JButton btnKeepMyVisibleState = new JButton(actKeepMyVisibleState);
-        btnKeepMyVisibleState.setName("button.keepmyvisiblestate");
-        add(btnKeepMyVisibleState, gc);
-
-        gc.gridx = 3;
-        gc.gridy = 5;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.33;
-        gc.weighty = 0.0;
-        add(lblMergedVisibleState = buildValueLabel("label.mergedvisiblestate"), gc);
-
-        gc.gridx = 4;
-        gc.gridy = 5;
-        gc.fill = GridBagConstraints.NONE;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.0;
-        gc.weighty = 0.0;
-        KeepTheirVisibleStateAction actKeepTheirVisibleState = new KeepTheirVisibleStateAction();
-        model.addObserver(actKeepTheirVisibleState);
-        JButton btnKeepTheirVisibleState = new JButton(actKeepTheirVisibleState);
-        btnKeepTheirVisibleState.setName("button.keeptheirvisiblestate");
-        add(btnKeepTheirVisibleState, gc);
-
-        gc.gridx = 5;
-        gc.gridy = 5;
-        gc.fill = GridBagConstraints.BOTH;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.33;
-        gc.weighty = 0.0;
-        add(lblTheirVisibleState = buildValueLabel("label.theirvisiblestate"), gc);
-
-        // ---------------------------------------------------
-        gc.gridx = 3;
-        gc.gridy = 6;
-        gc.fill = GridBagConstraints.NONE;
-        gc.anchor = GridBagConstraints.CENTER;
-        gc.weightx = 0.0;
-        gc.weighty = 0.0;
-        UndecideVisibleStateConflictAction actUndecideVisibleState = new UndecideVisibleStateConflictAction();
-        model.addObserver(actUndecideVisibleState);
-        JButton btnUndecideVisibleState = new JButton(actUndecideVisibleState);
-        btnUndecideVisibleState.setName("button.undecidevisiblestate");
-        add(btnUndecideVisibleState, gc);
-    }
-
     protected void buildReferrersRow() {
         GridBagConstraints gc = new GridBagConstraints();
 
@@ -362,7 +281,6 @@
         buildHeaderRow();
         buildCoordinateConflictRows();
         buildDeletedStateConflictRows();
-        buildVisibleStateRows();
         buildReferrersRow();
     }
 
@@ -393,24 +311,6 @@
             return tr("not deleted");
     }
 
-    public String visibleStateToString(Boolean visible) {
-        if (visible == null)
-            return tr("(none)");
-        if (visible)
-            return tr("visible (on the server)");
-        else
-            return tr("not visible (on the server)");
-    }
-
-    public String visibleStateToStringMerged(Boolean visible) {
-        if (visible == null)
-            return tr("(none)");
-        if (visible)
-            return tr("Keep a clone of the local version");
-        else
-            return tr("Physically delete from local dataset");
-    }
-
     public String referrersToString(List<OsmPrimitive> referrers) {
         if (referrers.isEmpty())
             return tr("(none)");
@@ -477,34 +377,6 @@
         }
     }
 
-    protected void updateVisibleState() {
-        lblMyVisibleState.setText(visibleStateToString(model.getMyVisibleState()));
-        lblMergedVisibleState.setText(visibleStateToStringMerged(model.getMergedVisibleState()));
-        lblTheirVisibleState.setText(visibleStateToString(model.getTheirVisibleState()));
-
-        if (! model.hasVisibleStateConflict()) {
-            lblMyVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
-            lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
-            lblTheirVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
-        } else {
-            if (!model.isDecidedVisibleState()) {
-                lblMyVisibleState.setBackground(BGCOLOR_UNDECIDED);
-                lblMergedVisibleState.setBackground(BGCOLOR_NO_CONFLICT);
-                lblTheirVisibleState.setBackground(BGCOLOR_UNDECIDED);
-            } else {
-                lblMyVisibleState.setBackground(
-                        model.isVisibleStateDecision(MergeDecisionType.KEEP_MINE)
-                        ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT
-                );
-                lblMergedVisibleState.setBackground(BGCOLOR_DECIDED);
-                lblTheirVisibleState.setBackground(
-                        model.isVisibleStateDecision(MergeDecisionType.KEEP_THEIR)
-                        ? BGCOLOR_DECIDED : BGCOLOR_NO_CONFLICT
-                );
-            }
-        }
-    }
-
     protected void updateReferrers() {
         lblMyReferrers.setText(referrersToString(model.getMyReferrers()));
         lblMyReferrers.setBackground(BGCOLOR_NO_CONFLICT);
@@ -515,7 +387,6 @@
     public void update(Observable o, Object arg) {
         updateCoordinates();
         updateDeletedState();
-        updateVisibleState();
         updateReferrers();
     }
 
@@ -613,101 +484,6 @@
         }
     }
 
-    class KeepMyVisibleStateAction extends AbstractAction implements Observer {
-        public KeepMyVisibleStateAction() {
-            putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeepmine"));
-            putValue(Action.SHORT_DESCRIPTION, tr("Keep my visible state"));
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            if (confirmKeepMine()) {
-                model.decideVisibleStateConflict(MergeDecisionType.KEEP_MINE);
-            }
-        }
-
-        public void update(Observable o, Object arg) {
-            setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState());
-        }
-
-        protected boolean confirmKeepMine() {
-            String [] options = {
-                    tr("Yes, reset the id"),
-                    tr("No, abort")
-            };
-            int ret = JOptionPane.showOptionDialog(
-                    null,
-                    tr("<html>To keep your local version, JOSM<br>"
-                            + "has to reset the id of primitive {0} to 0.<br>"
-                            + "On the next upload the server will assign<br>"
-                            + "it a new id.<br>"
-                            + "Do you agree?</html>",
-                            model.getMyPrimitive().getId()
-                    ),
-                    tr("Reset id to 0"),
-                    JOptionPane.YES_NO_OPTION,
-                    JOptionPane.QUESTION_MESSAGE,
-                    null,
-                    options,
-                    options[1]
-            );
-            return ret == JOptionPane.YES_OPTION;
-        }
-    }
-
-    class KeepTheirVisibleStateAction extends AbstractAction implements Observer {
-        public KeepTheirVisibleStateAction() {
-            putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeeptheir"));
-            putValue(Action.SHORT_DESCRIPTION, tr("Keep their visible state"));
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            if (confirmKeepTheir()){
-                model.decideVisibleStateConflict(MergeDecisionType.KEEP_THEIR);
-            }
-        }
-
-        public void update(Observable o, Object arg) {
-            setEnabled(model.hasVisibleStateConflict() && ! model.isDecidedVisibleState());
-        }
-
-        protected boolean confirmKeepTheir() {
-            String [] options = {
-                    tr("Yes, purge it"),
-                    tr("No, abort")
-            };
-            int ret = JOptionPane.showOptionDialog(
-                    null,
-                    tr("<html>JOSM will have to remove your local primitive with id {0}<br>"
-                            + "from the dataset.<br>"
-                            + "Do you agree?</html>",
-                            model.getMyPrimitive().getId()
-                    ),
-                    tr("Remove from dataset"),
-                    JOptionPane.YES_NO_OPTION,
-                    JOptionPane.QUESTION_MESSAGE,
-                    null,
-                    options,
-                    options[1]
-            );
-            return ret == JOptionPane.YES_OPTION;
-        }
-    }
-
-    class UndecideVisibleStateConflictAction extends AbstractAction implements Observer {
-        public UndecideVisibleStateConflictAction() {
-            putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagundecide"));
-            putValue(Action.SHORT_DESCRIPTION, tr("Undecide conflict between visible state"));
-        }
-
-        public void actionPerformed(ActionEvent e) {
-            model.decideVisibleStateConflict(MergeDecisionType.UNDECIDED);
-        }
-
-        public void update(Observable o, Object arg) {
-            setEnabled(model.hasVisibleStateConflict() && model.isDecidedVisibleState());
-        }
-    }
-
     public void deletePrimitive(boolean deleted) {
         if (deleted) {
             if (model.getMergedCoords() == null) {
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -38,7 +38,6 @@
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.RenameLayerAction;
-import org.openstreetmap.josm.command.PurgePrimitivesCommand;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.conflict.Conflict;
@@ -325,26 +324,18 @@
                 conflicts.add(c);
             }
         }
-        PurgePrimitivesCommand cmd = buildPurgeCommand();
-        if (cmd != null) {
-            Main.main.undoRedo.add(cmd);
-        }
         // repaint to make sure new data is displayed properly.
         Main.map.mapView.repaint();
-        warnNumNewConflicts(
-                numNewConflicts,
-                cmd == null ? 0 : cmd.getPurgedPrimitives().size()
-        );
+        warnNumNewConflicts(numNewConflicts);
     }
 
     /**
      * Warns the user about the number of detected conflicts
      *
      * @param numNewConflicts the number of detected conflicts
-     * @param numPurgedPrimitives the number of automatically purged objects
      */
-    protected void warnNumNewConflicts(int numNewConflicts, int numPurgedPrimitives) {
-        if (numNewConflicts == 0 && numPurgedPrimitives == 0) return;
+    protected void warnNumNewConflicts(int numNewConflicts) {
+        if (numNewConflicts == 0) return;
 
         String msg1 = trn(
                 "There was {0} conflict detected.",
@@ -352,32 +343,9 @@
                 numNewConflicts,
                 numNewConflicts
         );
-        String msg2 = trn(
-                "{0} conflict has been <strong>resolved automatically</strong> by purging {0} object<br>from the local dataset because it is deleted on the server.",
-                "{0} conflicts have been <strong>resolved automatically</strong> by purging {0} objects<br> from the local dataset because they are deleted on the server.",
-                numPurgedPrimitives,
-                numPurgedPrimitives
-        );
-        int numRemainingConflicts = numNewConflicts - numPurgedPrimitives;
-        String msg3 = "";
-        if (numRemainingConflicts >0) {
-            msg3 = trn(
-                    "{0} conflict remains to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve it.",
-                    "{0} conflicts remain to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve them.",
-                    numRemainingConflicts,
-                    numRemainingConflicts
-            );
-        }
 
         StringBuffer sb = new StringBuffer();
-        sb.append("<html>").append(msg1);
-        if (numPurgedPrimitives > 0) {
-            sb.append("<br>").append(msg2);
-        }
-        if (numRemainingConflicts > 0) {
-            sb.append("<br>").append(msg3);
-        }
-        sb.append("</html>");
+        sb.append("<html>").append(msg1).append("</html>");
         if (numNewConflicts > 0) {
             ButtonSpec[] options = new ButtonSpec[] {
                     new ButtonSpec(
@@ -402,49 +370,6 @@
         }
     }
 
-    /**
-     * Builds the purge command for primitives which can be purged automatically
-     * from the local dataset because they've been deleted on the
-     * server.
-     *
-     * @return the purge command. <code>null</code> if no primitives have to
-     * be purged
-     */
-    protected PurgePrimitivesCommand buildPurgeCommand() {
-        ArrayList<OsmPrimitive> toPurge = new ArrayList<OsmPrimitive>();
-        conflictLoop:
-            for (Conflict<?> c: conflicts) {
-                if (c.getMy().isDeleted() && !c.getTheir().isVisible()) {
-                    // Local and server version of the primitive are deleted. We
-                    // can purge it from the local dataset.
-                    //
-                    toPurge.add(c.getMy());
-                } else if (!c.getMy().isModified() && ! c.getTheir().isVisible()) {
-                    // We purge deleted *ways* and *relations* automatically if they are
-                    // deleted on the server and if they aren't modified in the local
-                    // dataset.
-                    //
-                    if (c.getMy() instanceof Way || c.getMy() instanceof Relation) {
-                        toPurge.add(c.getMy());
-                        continue conflictLoop;
-                    }
-                    // We only purge nodes if they aren't part of a modified way.
-                    // Otherwise the number of nodes of a modified way could drop
-                    // below 2 and we would lose the modified data when the way
-                    // gets purged.
-                    //
-                    for (OsmPrimitive parent: c.getMy().getReferrers()) {
-                        if (parent.isModified() && parent instanceof Way) {
-                            continue conflictLoop;
-                        }
-                    }
-                    toPurge.add(c.getMy());
-                }
-            }
-        if (toPurge.isEmpty()) return null;
-        PurgePrimitivesCommand cmd = new PurgePrimitivesCommand(this, toPurge);
-        return cmd;
-    }
 
     @Override public boolean isMergable(final Layer other) {
         return other instanceof OsmDataLayer;
Index: src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java	(working copy)
@@ -27,7 +27,6 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
-import org.openstreetmap.josm.gui.conflict.pair.properties.OperationCancelledException;
 import org.openstreetmap.josm.gui.help.HelpBrowser;
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -261,13 +260,9 @@
                     return;
                 }
             }
-            try {
-                Command cmd = resolver.buildResolveCommand();
-                Main.main.undoRedo.add(cmd);
-                closeDialog();
-            } catch(OperationCancelledException e) {
-                // do nothing. Exception already reported
-            }
+            Command cmd = resolver.buildResolveCommand();
+            Main.main.undoRedo.add(cmd);
+            closeDialog();
         }
 
         public void propertyChange(PropertyChangeEvent evt) {
Index: src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java	(revision 3339)
+++ src/org/openstreetmap/josm/gui/dialogs/relation/DownloadRelationMemberTask.java	(working copy)
@@ -120,6 +120,7 @@
                     .createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
             if (dataSet == null)
                 return;
+            dataSet.deleteInvisible();
             synchronized (this) {
                 if (cancelled) return;
                 objectReader = null;
Index: src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
===================================================================
--- src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(revision 3339)
+++ src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(working copy)
@@ -455,6 +455,9 @@
             fetchPrimitives(nodes,OsmPrimitiveType.NODE, progressMonitor);
             if (isCanceled())return null;
             fetchPrimitives(relations,OsmPrimitiveType.RELATION, progressMonitor);
+            if (outputDataSet != null) {
+                outputDataSet.deleteInvisible();
+            }
             return outputDataSet;
         } finally {
             progressMonitor.finishTask();
Index: src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java	(revision 3339)
+++ src/org/openstreetmap/josm/io/OsmServerBackreferenceReader.java	(working copy)
@@ -273,6 +273,9 @@
             visitor.merge();
             ret = visitor.getTargetDataSet();
             readIncompletePrimitives(ret, progressMonitor.createSubTaskMonitor(1, false));
+            if (ret != null) {
+                ret.deleteInvisible();
+            }
             return ret;
         } finally {
             progressMonitor.finishTask();
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 3339)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(working copy)
@@ -904,4 +904,17 @@
         relations.clear();
         allPrimitives.clear();
     }
+
+    /**
+     * Marks all "invisible" objects as deleted. These objects should be always marked as
+     * deleted when downloaded from the server. They can be undeleted later if necessary.
+     * 
+     */
+    public void deleteInvisible() {
+        for (OsmPrimitive primitive:allPrimitives) {
+            if (!primitive.isVisible()) {
+                primitive.setDeleted(true);
+            }
+        }
+    }
 }
Index: src/org/openstreetmap/josm/data/osm/DataSetMerger.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 3339)
+++ src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(working copy)
@@ -10,7 +10,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.logging.Logger;
 
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.conflict.ConflictCollection;
@@ -22,7 +21,6 @@
  *
  */
 public class DataSetMerger {
-    private static Logger logger = Logger.getLogger(DataSetMerger.class.getName());
 
     /** the collection of conflicts created during merging */
     private final ConflictCollection conflicts;
@@ -243,17 +241,8 @@
         if (target.getVersion() > source.getVersion())
             // target.version > source.version => keep target version
             return true;
-        if (! target.isVisible() && source.isVisible() && target.getVersion() == source.getVersion()) {
-            // should not happen
-            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
-            // wants to purge the target from the local dataset. He can't keep it unchanged
-            // because it was deleted on the server.
-            //
-            conflicts.add(target,source);
-        } else if (target.isIncomplete() && !source.isIncomplete()) {
+
+        if (target.isIncomplete() && !source.isIncomplete()) {
             // target is incomplete, source completes it
             // => merge source into target
             //
Index: src/org/openstreetmap/josm/command/VersionConflictResolveCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/VersionConflictResolveCommand.java	(revision 3339)
+++ src/org/openstreetmap/josm/command/VersionConflictResolveCommand.java	(working copy)
@@ -50,10 +50,16 @@
     public boolean executeCommand() {
         super.executeCommand();
         if (!conflict.getMy().isNew()) {
+            long myVersion = conflict.getMy().getVersion();
+            long theirVersion = conflict.getTheir().getVersion();
             conflict.getMy().setOsmId(
                     conflict.getMy().getId(),
-                    (int)Math.max(conflict.getMy().getVersion(), conflict.getTheir().getVersion())
+                    (int)Math.max(myVersion, theirVersion)
             );
+            // update visiblity state
+            if (theirVersion >= myVersion) {
+                conflict.getMy().setVisible(conflict.getTheir().isVisible());
+            }
         }
         getLayer().getConflicts().remove(conflict);
         rememberConflict(conflict);
Index: src/org/openstreetmap/josm/command/UndeletePrimitivesCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/UndeletePrimitivesCommand.java	(revision 3339)
+++ src/org/openstreetmap/josm/command/UndeletePrimitivesCommand.java	(working copy)
@@ -25,6 +25,7 @@
  * the node into a new node which can be uploaded to the server.
  *
  */
+@Deprecated
 public class UndeletePrimitivesCommand extends ConflictResolveCommand {
     //static private final Logger logger = Logger.getLogger(UndeletePrimitivesCommand.class.getName());
 
Index: src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(revision 3339)
+++ src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(working copy)
@@ -39,6 +39,7 @@
  * which would result in an non resolvable conflict.
  *
  */
+@Deprecated
 public class PurgePrimitivesCommand extends ConflictResolveCommand{
 
     static private final Logger logger = Logger.getLogger(PurgePrimitivesCommand.class.getName());
