Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java	(revision 23970)
@@ -171,4 +171,16 @@
 		}
 		return TagUtils.getAddrCountryValue(osmObject);
+	}
+	
+	/**
+	 * Removes all addresss related tags from the node or way.
+	 */
+	public void removeAllAddressTags() {
+		removeOSMTag(TagUtils.ADDR_CITY_TAG);
+		removeOSMTag(TagUtils.ADDR_COUNTRY_TAG);
+		removeOSMTag(TagUtils.ADDR_POSTCODE_TAG);
+		removeOSMTag(TagUtils.ADDR_HOUSENUMBER_TAG);
+		removeOSMTag(TagUtils.ADDR_STATE_TAG);
+		removeOSMTag(TagUtils.ADDR_STREET_TAG);
 	}
 	
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/ICommandListener.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/ICommandListener.java	(revision 23970)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/ICommandListener.java	(revision 23970)
@@ -0,0 +1,26 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.openstreetmap.josm.plugins.fixAddresses;
+
+import org.openstreetmap.josm.command.Command;
+
+public interface ICommandListener {
+	/**
+	 * Called by a node entity if a command has been created. Clients may collect
+	 * these commands to define a sequence command.
+	 * @param entity
+	 * @param command
+	 */
+	public void commandIssued(INodeEntity entity, Command command);
+}
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java	(revision 23970)
@@ -58,3 +58,15 @@
 	 */
 	public LatLon getCoor();
+	
+	/**
+	 * Adds a command listener.
+	 * @param listener
+	 */
+	public void addCommandListener(ICommandListener listener);
+	
+	/**
+	 * Removes a command listener.
+	 * @param listener
+	 */
+	public void removeCommandListener(ICommandListener listener);
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java	(revision 23970)
@@ -19,6 +19,6 @@
 import java.util.List;
 
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.ChangePropertyCommand;
+import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.BBox;
@@ -29,5 +29,6 @@
 public class NodeEntityBase implements INodeEntity, Comparable<INodeEntity> {
 	public static final String ANONYMOUS = tr("No name");
-	private static List<IAddressEditContainerListener> listeners = new ArrayList<IAddressEditContainerListener>();
+	private static List<IAddressEditContainerListener> containerListeners = new ArrayList<IAddressEditContainerListener>();
+	private List<ICommandListener> cmdListeners = new ArrayList<ICommandListener>();
 	
 	protected OsmPrimitive osmObject;
@@ -53,5 +54,5 @@
 	 */
 	public static void addChangedListener(IAddressEditContainerListener listener) {
-		listeners.add(listener);
+		containerListeners.add(listener);
 	}
 	
@@ -61,5 +62,5 @@
 	 */
 	public static void removeChangedListener(IAddressEditContainerListener listener) {
-		listeners.remove(listener);
+		containerListeners.remove(listener);
 	}
 	
@@ -68,8 +69,40 @@
 	 */
 	protected static void fireEntityChanged(INodeEntity entity) {
-		for (IAddressEditContainerListener listener : listeners) {
+		for (IAddressEditContainerListener listener : containerListeners) {
 			listener.entityChanged(entity);
 		}
 	}
+	
+	/**
+	 * Adds a command listener.
+	 * @param listener
+	 */
+	public void addCommandListener(ICommandListener listener) {
+		cmdListeners.add(listener);
+	}
+	
+	/**
+	 * Removes a command listener.
+	 * @param listener
+	 */
+	public void removeCommandListener(ICommandListener listener) {
+		cmdListeners.remove(listener);
+	}
+	
+	/**
+	 * Notifies clients that an entity has issued a command.
+	 *
+	 * @param source the entity that issued the command.
+	 * @param cmd the command to execute.
+	 */
+	protected void fireCommandIssued(Command cmd) {
+		if (cmdListeners.size() == 0) {
+			throw new RuntimeException("Object has no TX context: " + this);
+		}
+		
+		for (ICommandListener l : cmdListeners) {
+			l.commandIssued(this, cmd);
+		}
+	}	
 
 	public OsmPrimitive getOsmObject() {
@@ -79,5 +112,4 @@
 	@Override
 	public List<INodeEntity> getChildren() {
-		// TODO Auto-generated method stub
 		return null;
 	}
@@ -109,24 +141,22 @@
 	 * @param tag The tag to change.
 	 * @param newValue The new value for the tag.
+	 * @param cmd The surrounding command sequence
 	 */
 	protected void setOSMTag(String tag, String newValue) {
-		OsmPrimitive oldObject = osmObject;
-		OsmPrimitive newObject = null;
-			
-		// I would appreciate a clone method...
-		if (oldObject instanceof Node) {
-			newObject = new Node();
-		} else if (oldObject instanceof Way) {
-			newObject = new Way();
-		}
+		if (StringUtils.isNullOrEmpty(tag)) return;
 		
-		if (newObject != null) {
-			newObject.cloneFrom(oldObject);
-			newObject.put(tag, newValue);
-			Main.main.undoRedo.add( new ChangeCommand(oldObject, newObject));
+		if (osmObject != null && osmObject.hasKey(tag)) {
+			fireCommandIssued(new ChangePropertyCommand(osmObject, tag, newValue));
 			fireEntityChanged(this);
-		} else {
-			throw new RuntimeException("Cannot modify tag for " + osmObject);
-		}
+		} 
+	}
+	
+	/**
+	 * Removes the given tag from the OSM object.
+	 *
+	 * @param tag the tag
+	 */
+	protected void removeOSMTag(String tag) {
+		setOSMTag(tag, null); // a value of null removes the tag
 	}
 
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AbstractAddressEditAction.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AbstractAddressEditAction.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AbstractAddressEditAction.java	(revision 23970)
@@ -15,9 +15,16 @@
 
 import java.awt.event.ActionEvent;
-
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.plugins.fixAddresses.AddressEditContainer;
 import org.openstreetmap.josm.plugins.fixAddresses.IAddressEditContainerListener;
+import org.openstreetmap.josm.plugins.fixAddresses.ICommandListener;
 import org.openstreetmap.josm.plugins.fixAddresses.INodeEntity;
+import org.openstreetmap.josm.plugins.fixAddresses.StringUtils;
 
 /**
@@ -34,7 +41,9 @@
 
 @SuppressWarnings("serial")
-public abstract class AbstractAddressEditAction extends JosmAction implements IAddressEditContainerListener {	
+public abstract class AbstractAddressEditAction extends JosmAction implements IAddressEditContainerListener, ICommandListener {	
 	private AddressEditSelectionEvent event;
 	protected AddressEditContainer container;
+	private List<Command> commands;
+	private String txName;
 
 	/**
@@ -167,3 +176,71 @@
 		updateEnabledState();		
 	}
+	
+	/**
+	 * Begins the transaction (command sequence). Must be called by every subclass before
+	 * any modification on OSM objects starts.
+	 *
+	 * @param txName the name of the transaction (e. g. "change address tags").
+	 */
+	public void beginTransaction(String txName) {
+		if (commands != null && commands.size() > 0) {
+			throw new RuntimeException("TX has not been closed (missing finishTransaction?)");
+		}
+		
+		commands = new ArrayList<Command>();
+		if (StringUtils.isNullOrEmpty(txName)) {
+			throw new RuntimeException("Transaction must have a name");
+		}
+		this.txName = txName;
+	}
+	
+	/**
+	 * Finishes the transaction and passes the command sequence to the framework.
+	 */
+	public void finishTransaction() {
+		if (commands == null) {
+			throw new RuntimeException("No command list available. Did you forget to call beginTransaction?");
+		}
+		// execute the command
+		Main.main.undoRedo.add(new SequenceCommand(txName, commands));
+		commands.clear();
+		container.invalidate();
+	}
+	
+	/**
+	 * Begins the transaction for a single object.
+	 *
+	 * @param entity the entity
+	 */
+	public void beginObjectTransaction(INodeEntity entity) {
+		if (entity != null) {
+			entity.addCommandListener(this);
+		} else {
+			throw new RuntimeException("Entity must not be null");
+		}
+	}
+	
+	/**
+	 * Finishes the transaction for a single object.
+	 *
+	 * @param entity the entity
+	 */
+	public void finishObjectTransaction(INodeEntity entity) {
+		if (entity != null) {
+			entity.removeCommandListener(this);
+		} else {
+			throw new RuntimeException("Entity must not be null");
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.fixAddresses.ICommandListener#commandIssued(org.openstreetmap.josm.plugins.fixAddresses.INodeEntity, org.openstreetmap.josm.command.Command)
+	 */
+	@Override
+	public void commandIssued(INodeEntity entity, Command command) {
+		if (commands == null) {
+			throw new RuntimeException("No command list available. Did you forget to call beginTransaction?");
+		}
+		commands.add(command);
+	}
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditDialog.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditDialog.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditDialog.java	(revision 23970)
@@ -75,4 +75,5 @@
 	private GuessAddressDataAction guessAddressAction = new GuessAddressDataAction();
 	private SelectAddressesInMapAction selectAddressesInMapAction = new SelectAddressesInMapAction();
+	private RemoveAddressTagsAction removeAddressTagsAction = new RemoveAddressTagsAction();
 	
 	private AbstractAddressEditAction[] actions = new AbstractAddressEditAction[] {
@@ -80,5 +81,6 @@
 		guessAddressAction,
 		applyAllGuessesAction,
-		selectAddressesInMapAction
+		selectAddressesInMapAction,
+		removeAddressTagsAction
 	};
 	private JLabel streetLabel;
@@ -145,4 +147,10 @@
 				
 				unresolvedButtons.add(new JSeparator());
+				
+				SideButton removeAddressTags = new SideButton(removeAddressTagsAction);															   
+				unresolvedButtons.add(removeAddressTags);
+				
+				unresolvedButtons.add(new JSeparator());
+				
 				SideButton selectInMap = new SideButton(selectAddressesInMapAction);															   
 				unresolvedButtons.add(selectInMap);
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/ApplyAllGuessesAction.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/ApplyAllGuessesAction.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/ApplyAllGuessesAction.java	(revision 23970)
@@ -50,8 +50,12 @@
 
 	private void applyGuesses(List<AddressNode> addrToFix) {
+		beginTransaction(tr("Applied guessed values"));
 		List<AddressNode> addrToFixShadow = new ArrayList<AddressNode>(addrToFix);
 		for (AddressNode aNode : addrToFixShadow) {
+			beginObjectTransaction(aNode);
 			aNode.applyAllGuesses();
+			finishObjectTransaction(aNode);
 		}
+		finishTransaction();
 	}
 
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AssignAddressToStreetAction.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AssignAddressToStreetAction.java	(revision 23969)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AssignAddressToStreetAction.java	(revision 23970)
@@ -26,5 +26,5 @@
  * 
  */
-public class AssignAddressToStreetAction extends AbstractAddressEditAction {
+public class AssignAddressToStreetAction extends AbstractAddressEditAction  {
 
 	public AssignAddressToStreetAction() {
@@ -43,10 +43,15 @@
 	public void addressEditActionPerformed(AddressEditSelectionEvent ev) {		
 		StreetNode streetNode = ev.getSelectedStreet();
-				
+						
 		if (streetNode != null && ev.getSelectedUnresolvedAddresses() != null) {
+			beginTransaction(tr("Set street name") + " '" + streetNode.getName() + "'");
 			for (AddressNode addrNode : ev.getSelectedUnresolvedAddresses()) {
-				addrNode.assignStreet(streetNode);				
+				beginObjectTransaction(addrNode);
+				addrNode.assignStreet(streetNode);
+				finishObjectTransaction(addrNode);
 			}
+			finishTransaction();
 		}
+		
 	}
 
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/RemoveAddressTagsAction.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/RemoveAddressTagsAction.java	(revision 23970)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/RemoveAddressTagsAction.java	(revision 23970)
@@ -0,0 +1,58 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.openstreetmap.josm.plugins.fixAddresses.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.plugins.fixAddresses.AddressEditContainer;
+import org.openstreetmap.josm.plugins.fixAddresses.AddressNode;
+
+@SuppressWarnings("serial")
+public class RemoveAddressTagsAction extends AbstractAddressEditAction {
+
+	public RemoveAddressTagsAction() {
+		super(tr("Remove address tags"), "removeaddrtags_24", tr("Removes address related tags from the object."));
+	}
+
+	@Override
+	public void addressEditActionPerformed(AddressEditSelectionEvent ev) {
+		beginTransaction(tr("Remove address tags"));
+		for (AddressNode aNode : ev.getSelectedUnresolvedAddresses()) {
+			beginObjectTransaction(aNode);
+			aNode.removeAllAddressTags();
+			finishObjectTransaction(aNode);
+		}
+		finishTransaction();		
+	}
+
+	@Override
+	public void addressEditActionPerformed(AddressEditContainer container) {
+		// do nothing
+	}
+
+	@Override
+	protected void updateEnabledState(AddressEditContainer container) {
+		setEnabled(false);
+	}
+
+	@Override
+	protected void updateEnabledState(AddressEditSelectionEvent event) {
+		if (event == null) {
+			setEnabled(false);
+		}
+		
+		setEnabled(event.getSelectedUnresolvedAddresses() != null);
+	}
+
+}
