Index: trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 9291)
+++ trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 9292)
@@ -6,4 +6,5 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
+import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -18,6 +19,10 @@
 import java.util.Set;
 
+import javax.swing.AbstractButton;
+import javax.swing.ButtonGroup;
+import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JToggleButton;
 
 import org.openstreetmap.josm.Main;
@@ -32,7 +37,13 @@
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Shortcut;
+import org.openstreetmap.josm.tools.UserCancelException;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -163,4 +174,118 @@
 
     /**
+     * Provides toggle buttons to allow the user choose the existing node, the new nodes, or all of them.
+     */
+    private static class ExistingBothNewChoice {
+        final AbstractButton oldNode = new JToggleButton(tr("Existing node"), ImageProvider.get("dialogs/conflict/tagkeeptheir"));
+        final AbstractButton bothNodes = new JToggleButton(tr("Both nodes"), ImageProvider.get("dialogs/conflict/tagundecide"));
+        final AbstractButton newNode = new JToggleButton(tr("New node"), ImageProvider.get("dialogs/conflict/tagkeepmine"));
+
+        ExistingBothNewChoice(final boolean preselectNew) {
+            final ButtonGroup tagsGroup = new ButtonGroup();
+            tagsGroup.add(oldNode);
+            tagsGroup.add(bothNodes);
+            tagsGroup.add(newNode);
+            tagsGroup.setSelected((preselectNew ? newNode : oldNode).getModel(), true);
+        }
+    }
+
+    /**
+     * A dialog allowing the user decide whether the tags/memberships of the existing node should afterwards be at
+     * the existing node, the new nodes, or all of them.
+     */
+    static final class PropertiesMembershipDialog extends ExtendedDialog {
+
+        final ExistingBothNewChoice tags;
+        final ExistingBothNewChoice memberships;
+
+        private PropertiesMembershipDialog(boolean preselectNew, boolean queryTags, boolean queryMemberships) {
+            super(Main.parent, tr("Tags / Memberships"), new String[]{tr("Unglue"), tr("Cancel")});
+            setButtonIcons(new String[]{"unglueways", "cancel"});
+
+            final JPanel content = new JPanel(new GridBagLayout());
+
+            if (queryTags) {
+                content.add(new JLabel(tr("Where should the tags of the node be put?")), GBC.std(1, 1).span(3).insets(0, 20, 0, 0));
+                tags = new ExistingBothNewChoice(preselectNew);
+                content.add(tags.oldNode, GBC.std(1, 2));
+                content.add(tags.bothNodes, GBC.std(2, 2));
+                content.add(tags.newNode, GBC.std(3, 2));
+            } else {
+                tags = null;
+            }
+
+            if (queryMemberships) {
+                content.add(new JLabel(tr("Where should the memberships of this node be put?")), GBC.std(1, 3).span(3).insets(0, 20, 0, 0));
+                memberships = new ExistingBothNewChoice(preselectNew);
+                content.add(memberships.oldNode, GBC.std(1, 4));
+                content.add(memberships.bothNodes, GBC.std(2, 4));
+                content.add(memberships.newNode, GBC.std(3, 4));
+            } else {
+                memberships = null;
+            }
+
+            setContent(content);
+            setResizable(false);
+        }
+
+        static PropertiesMembershipDialog showIfNecessary(Iterable<Node> selectedNodes, boolean preselectNew) throws UserCancelException {
+            final boolean tagged = isTagged(selectedNodes);
+            final boolean usedInRelations = isUsedInRelations(selectedNodes);
+            if (tagged || usedInRelations) {
+                final PropertiesMembershipDialog dialog = new PropertiesMembershipDialog(preselectNew, tagged, usedInRelations);
+                dialog.showDialog();
+                if (dialog.getValue() != 1) {
+                    throw new UserCancelException();
+                }
+                return dialog;
+            }
+            return null;
+        }
+
+        private static boolean isTagged(final Iterable<Node> existingNodes) {
+            return Utils.exists(existingNodes, new Predicate<Node>() {
+                @Override
+                public boolean evaluate(final Node selectedNode) {
+                    return selectedNode.hasKeys();
+                }
+            });
+        }
+
+        private static boolean isUsedInRelations(final Iterable<Node> existingNodes) {
+            return Utils.exists(existingNodes, new Predicate<Node>() {
+                @Override
+                public boolean evaluate(final Node selectedNode) {
+                    return Utils.exists(selectedNode.getReferrers(), OsmPrimitive.relationPredicate);
+                }
+            });
+        }
+
+        void update(final Node existingNode, final List<Node> newNodes, final Collection<Command> cmds) {
+            updateMemberships(existingNode, newNodes, cmds);
+            updateProperties(existingNode, newNodes, cmds);
+        }
+
+        private void updateProperties(final Node existingNode, final Iterable<Node> newNodes, final Collection<Command> cmds) {
+            if (tags != null && tags.newNode.isSelected()) {
+                final Node newSelectedNode = new Node(existingNode);
+                newSelectedNode.removeAll();
+                cmds.add(new ChangeCommand(existingNode, newSelectedNode));
+            } else if (tags != null && tags.oldNode.isSelected()) {
+                for (Node newNode : newNodes) {
+                    newNode.removeAll();
+                }
+            }
+        }
+
+        private void updateMemberships(final Node existingNode, final List<Node> newNodes, final Collection<Command> cmds) {
+            if (memberships != null && memberships.bothNodes.isSelected()) {
+                fixRelations(existingNode, cmds, newNodes, false);
+            } else if (memberships != null && memberships.newNode.isSelected()) {
+                fixRelations(existingNode, cmds, newNodes, true);
+            }
+        }
+    }
+
+    /**
      * Assumes there is one tagged Node stored in selectedNode that it will try to unglue.
      * (i.e. copy node and remove all tags from the old one. Relations will not be removed)
@@ -170,10 +295,17 @@
         List<Command> cmds = new LinkedList<>();
 
-        Node c = new Node(selectedNode);
-        c.removeAll();
-        getCurrentDataSet().clearSelection(c);
-        cmds.add(new ChangeCommand(selectedNode, c));
-
-        Node n = new Node(selectedNode, true);
+        final PropertiesMembershipDialog dialog;
+        try {
+            dialog = PropertiesMembershipDialog.showIfNecessary(Collections.singleton(selectedNode), true);
+        } catch (UserCancelException e1) {
+            return;
+        }
+
+        final Node n = new Node(selectedNode, true);
+
+        cmds.add(new AddCommand(n));
+        if (dialog != null) {
+            dialog.update(selectedNode, Collections.singletonList(n), cmds);
+        }
 
         // If this wasn't called from menu, place it where the cursor is/was
@@ -182,8 +314,4 @@
             n.setCoor(mv.getLatLon(mv.lastMEvent.getX(), mv.lastMEvent.getY()));
         }
-
-        cmds.add(new AddCommand(n));
-
-        fixRelations(selectedNode, cmds, Collections.singletonList(n));
 
         Main.main.undoRedo.add(new SequenceCommand(tr("Unglued Node"), cmds));
@@ -334,5 +462,5 @@
      * @param newNodes List of nodes that contain the new node
      */
-    private void fixRelations(Node originalNode, List<Command> cmds, List<Node> newNodes) {
+    private static void fixRelations(Node originalNode, Collection<Command> cmds, List<Node> newNodes, boolean removeOldMember) {
         // modify all relations containing the node
         for (Relation r : OsmPrimitive.getFilteredList(originalNode.getReferrers(), Relation.class)) {
@@ -357,7 +485,10 @@
             if (newRel != null) {
                 if (rolesToReAdd != null) {
-                    for (Node n : newNodes) {
-                        for (Map.Entry<String, Integer> role : rolesToReAdd.entrySet()) {
+                    for (Map.Entry<String, Integer> role : rolesToReAdd.entrySet()) {
+                        for (Node n : newNodes) {
                             newRel.addMember(role.getValue() + 1, new RelationMember(role.getKey(), n));
+                        }
+                        if (removeOldMember) {
+                            newRel.removeMember(role.getValue());
                         }
                     }
@@ -376,4 +507,11 @@
         List<Command> cmds = new LinkedList<>();
         List<Node> newNodes = new LinkedList<>();
+
+        final PropertiesMembershipDialog dialog;
+        try {
+            dialog = PropertiesMembershipDialog.showIfNecessary(Collections.singleton(selectedNode), false);
+        } catch (UserCancelException e) {
+            return;
+        }
 
         if (selectedWay == null) {
@@ -400,5 +538,8 @@
         }
 
-        fixRelations(selectedNode, cmds, newNodes);
+        if (dialog != null) {
+            dialog.update(selectedNode, newNodes, cmds);
+        }
+
         execCommands(cmds, newNodes);
     }
@@ -457,9 +598,16 @@
         }
         cmds.add(new ChangeNodesCommand(way, newNodes));
-        // Update relation
-        fixRelations(selectedNode, cmds, addNodes);
-        execCommands(cmds, addNodes);
-        return true;
-     }
+        try {
+            final PropertiesMembershipDialog dialog = PropertiesMembershipDialog.showIfNecessary(Collections.singleton(selectedNode), false);
+            if (dialog != null) {
+                dialog.update(selectedNode, addNodes, cmds);
+            }
+            execCommands(cmds, addNodes);
+            return true;
+        } catch (UserCancelException ignore) {
+            Main.debug(ignore.getMessage());
+        }
+        return false;
+    }
 
     /**
@@ -472,8 +620,17 @@
         Way tmpWay = selectedWay;
 
+        final PropertiesMembershipDialog dialog;
+        try {
+            dialog = PropertiesMembershipDialog.showIfNecessary(selectedNodes, false);
+        } catch (UserCancelException e) {
+            return;
+        }
+
         for (Node n : selectedNodes) {
             List<Node> newNodes = new LinkedList<>();
             tmpWay = modifyWay(n, tmpWay, cmds, newNodes);
-            fixRelations(n, cmds, newNodes);
+            if (dialog != null) {
+                dialog.update(n, newNodes, cmds);
+            }
             allNewNodes.addAll(newNodes);
         }
