Index: applications/editors/josm/plugins/utilsplugin2/src/utilsplugin2/dumbutils/ReplaceGeometryAction.java
===================================================================
--- applications/editors/josm/plugins/utilsplugin2/src/utilsplugin2/dumbutils/ReplaceGeometryAction.java	(revision 27623)
+++ applications/editors/josm/plugins/utilsplugin2/src/utilsplugin2/dumbutils/ReplaceGeometryAction.java	(revision 27624)
@@ -10,10 +10,13 @@
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.command.*;
-import org.openstreetmap.josm.data.coor.LatLon;
 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.RelationToChildReference;
+import org.openstreetmap.josm.data.osm.TagCollection;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
+import org.openstreetmap.josm.gui.conflict.tags.CombinePrimitiveResolverDialog;
+import org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil;
 import static org.openstreetmap.josm.tools.I18n.tr;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -81,4 +84,12 @@
         AbstractMap<String, String> nodeTags = (AbstractMap<String, String>) node.getKeys();
 
+        // merge tags
+        Collection<Command> tagResolutionCommands = getTagConflictResolutionCommands(node, way);
+        if (tagResolutionCommands == null) {
+            // user canceled tag merge dialog
+            return;
+        }
+        commands.addAll(tagResolutionCommands);
+        
         // replace sacrificial node in way with node that is being upgraded
         if (nodeToReplace != null) {
@@ -104,10 +115,4 @@
             // no node to replace, so just delete the original node
             commands.add(new DeleteCommand(node));
-        }
-
-        // Copy tags from node
-        // TODO: use merge tag conflict dialog instead
-        for (String key : nodeTags.keySet()) {
-            commands.add(new ChangePropertyCommand(way, key, nodeTags.get(key)));
         }
 
@@ -164,4 +169,14 @@
         }
 
+        List<Command> commands = new ArrayList<Command>();
+                
+        // merge tags
+        Collection<Command> tagResolutionCommands = getTagConflictResolutionCommands(geometry, way);
+        if (tagResolutionCommands == null) {
+            // user canceled tag merge dialog
+            return;
+        }
+        commands.addAll(tagResolutionCommands);
+        
         // Prepare a list of nodes that are not used anywhere except in the way
         Collection<Node> nodePool = getUnimportantNodes(way);
@@ -199,5 +214,4 @@
 
         // Now do the replacement
-        List<Command> commands = new ArrayList<Command>();
         commands.add(new ChangeNodesCommand(way, geometryNodes));
 
@@ -205,8 +219,4 @@
         for( Node node : nodeAssoc.keySet() )
             commands.add(new MoveCommand(nodeAssoc.get(node), node.getCoor()));
-
-        // Copy tags from temporary way (source etc.)
-        for( String key : geometry.keySet() )
-            commands.add(new ChangePropertyCommand(way, key, geometry.get(key)));
 
         // Remove geometry way from selection
@@ -296,4 +306,43 @@
     }
     
+     /**
+     * Merge tags from source to target object, showing resolution dialog if
+     * needed.
+     *
+     * @param source
+     * @param target
+     * @return
+     */
+    public List<Command> getTagConflictResolutionCommands(OsmPrimitive source, OsmPrimitive target) {
+        Collection<OsmPrimitive> primitives = Arrays.asList(source, target);
+        
+        Set<RelationToChildReference> relationToNodeReferences = RelationToChildReference.getRelationToChildReferences(primitives);
+
+        // build the tag collection
+        TagCollection tags = TagCollection.unionOfAllPrimitives(primitives);
+        TagConflictResolutionUtil.combineTigerTags(tags);
+        TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing(tags, primitives);
+        TagCollection tagsToEdit = new TagCollection(tags);
+        TagConflictResolutionUtil.completeTagCollectionForEditing(tagsToEdit);
+
+        // launch a conflict resolution dialog, if necessary
+        CombinePrimitiveResolverDialog dialog = CombinePrimitiveResolverDialog.getInstance();
+        dialog.getTagConflictResolverModel().populate(tagsToEdit, tags.getKeysWithMultipleValues());
+        dialog.getRelationMemberConflictResolverModel().populate(relationToNodeReferences);
+        dialog.setTargetPrimitive(target);
+        dialog.prepareDefaultDecisions();
+
+        // conflict resolution is necessary if there are conflicts in the merged tags
+        // or if at least one of the merged nodes is referred to by a relation
+        if (!tags.isApplicableToPrimitive() || relationToNodeReferences.size() > 1) {
+            dialog.setVisible(true);
+            if (dialog.isCanceled()) {
+                return null;
+            }
+        }
+        return dialog.buildResolutionCommands();
+    }
+
+    
     /**
      * Find node from the collection which is nearest to <tt>node</tt>. Max distance is taken in consideration.
