Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 477)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 478)
@@ -33,4 +33,8 @@
 	private final DataSet mergeds;
 
+	private final HashMap<Long, Node> nodeshash = new HashMap<Long, Node>();
+	private final HashMap<Long, Way> wayshash = new HashMap<Long, Way>();
+	private final HashMap<Long, Relation> relshash = new HashMap<Long, Relation>();
+
 	/**
 	 * A list of all primitives that got replaced with other primitives.
@@ -44,4 +48,8 @@
 		this.ds = ds;
 		this.mergeds = mergeds;
+
+		for (Node n : ds.nodes) if (n.id != 0) nodeshash.put(n.id, n);
+		for (Way w : ds.ways) if (w.id != 0) wayshash.put(w.id, w);
+		for (Relation r : ds.relations) if (r.id != 0) relshash.put(r.id, r);
 	}
 
@@ -51,5 +59,5 @@
 	 */
 	public void visit(Node other) {
-		if (mergeAfterId(ds.nodes, other))
+		if (mergeAfterId(ds.nodes, nodeshash, other))
 			return;
 
@@ -82,5 +90,5 @@
 	public void visit(Way other) {
 		fixWay(other);
-		if (mergeAfterId(ds.ways, other))
+		if (mergeAfterId(ds.ways, wayshash, other))
 			return;
 
@@ -117,5 +125,5 @@
 	public void visit(Relation other) {
 		fixRelation(other);
-		if (mergeAfterId(ds.relations, other))
+		if (mergeAfterId(ds.relations, relshash, other))
 			return;
 
@@ -275,5 +283,15 @@
 	 * @return <code>true</code>, if no merge is needed or merge is performed already.
 	 */
-	private <P extends OsmPrimitive> boolean mergeAfterId(Collection<P> primitives, P other) {
+	private <P extends OsmPrimitive> boolean mergeAfterId(
+			Collection<P> primitives, HashMap<Long, P> hash, P other) {
+		// Fast-path merging of identical objects
+		if (hash.containsKey(other.id)) {
+			P my = hash.get(other.id);
+			if (my.realEqual(other, true)) {
+				merged.put(other, my);
+				return true;
+			}
+		}
+
 		for (P my : primitives) {
 			Date myd = my.timestamp == null ? new Date(0) : my.getTimestamp();
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 477)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 478)
@@ -251,12 +251,13 @@
 		buttonPanel.add(deleteButton);
 
-		mergeButton.setToolTipText(tr("Merge the selected layer into the layer directly below."));
+		mergeButton.setToolTipText(tr("Merge the layer directly below into the selected layer."));
 		mergeButton.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
-				Layer lFrom = (Layer)instance.getSelectedValue();
-				Layer lTo = (Layer)model.get(instance.getSelectedIndex()+1);
+				Layer lTo = (Layer)instance.getSelectedValue();
+				Layer lFrom = (Layer)model.get(instance.getSelectedIndex()+1);
 				lTo.mergeFrom(lFrom);
-				instance.setSelectedValue(lTo, true);
 				mapView.removeLayer(lFrom);
+				updateButtonEnabled();
+				mapView.repaint();
 			}
 		});
@@ -277,5 +278,5 @@
 		boolean enable = model.getSize() > 1;
 		enable = enable && sel < model.getSize()-1;
-		enable = enable && l.isMergable((Layer)model.get(sel+1));
+		enable = enable && ((Layer)model.get(sel+1)).isMergable(l);
 		mergeButton.setEnabled(enable);
 		upButton.setEnabled(sel > 0);
