Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(revision 13892)
+++ binaries/data/mods/public/gui/session/input.js	(working copy)
@@ -1848,6 +1848,12 @@
 					Engine.CameraMoveTo(focusTarget.x, focusTarget.z);
 				
 				break;
+			case "back-to-work":
+				backToWork();
+				break;
+			case "unload-all-back-to-work":
+				unloadAllBackToWork();
+				break;
 			default:
 				break;
 			}
@@ -2110,6 +2116,33 @@
 	Engine.PostNetworkCommand({"type": "unload-all", "garrisonHolders": garrisonHolders});
 }
 
+function backToWork()
+{
+	// Filter out all entities that can't go back to work.
+	var workers = g_Selection.toList().filter(function(e) {
+		var state = GetEntityState(e);
+		if (state && (hasClass(state, "Worker") || hasClass(state, "Trader")))
+			return true;
+		return false;
+	});
+	
+	Engine.PostNetworkCommand({"type": "back-to-work", "workers": workers});
+	
+}
+
+function unloadAllBackToWork()
+{
+	// Filter out all entities that aren't garrisonable.
+	var garrisonHolders = g_Selection.toList().filter(function(e) {
+		var state = GetEntityState(e);
+		if (state && state.garrisonHolder)
+			return true;
+		return false;
+	});
+
+	Engine.PostNetworkCommand({"type": "unload-all-back-to-work", "garrisonHolders": garrisonHolders});
+}
+
 function clearSelection()
 {
 	if(inputState==INPUT_BUILDING_PLACEMENT || inputState==INPUT_BUILDING_WALL_PATHING)
Index: binaries/data/mods/public/gui/session/utility_functions.js
===================================================================
--- binaries/data/mods/public/gui/session/utility_functions.js	(revision 13892)
+++ binaries/data/mods/public/gui/session/utility_functions.js	(working copy)
@@ -293,6 +293,24 @@
 		    "icon": "focus-rally.png"
 		});
 	}
+	
+	if (hasClass(entState, "Worker") || hasClass(entState, "Trader"))
+	{
+		commands.push({
+		    "name": "back-to-work",
+		    "tooltip": "Back to Work",
+		    "icon": "production.png"
+		});
+	}
+	
+	if (entState.garrisonHolder)
+	{
+		commands.push({
+		    "name": "unload-all-back-to-work",
+		    "tooltip": "Unload All Units and Send the Workers Back to Work",
+		    "icon": "production.png"
+		});
+	}
 
 	return commands;
 }
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(revision 13892)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(working copy)
@@ -263,7 +263,7 @@
  * Ejects units and orders them to move to the Rally Point.
  * Returns true if successful, false if not
  */
-GarrisonHolder.prototype.PerformEject = function(entities, forced)
+GarrisonHolder.prototype.PerformEject = function(entities, forced, backToWork)
 {
 	if (!this.IsGarrisoningAllowed() && !forced)
 		return false;
@@ -283,7 +283,29 @@
 			success = false;
 	}
 
-	this.OrderWalkToRallyPoint(ejectedEntities);
+	if (backToWork)
+	{
+		// Filter the entities who shall go back to work and those who shall not.
+		var workers = [];
+		var nonWorkers = [];
+		
+		ejectedEntities.forEach(function(e) {
+		var cmpIdentity = Engine.QueryInterface(e, IID_Identity);
+		var classes = cmpIdentity.GetClassesList();
+		if (classes.some(function(c) {return (c == "Worker" || c == "Trader");}))
+			workers.push(e);
+		else
+			nonWorkers.push(e);
+		});
+		
+		var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+		ProcessCommand(cmpOwnership.GetOwner(), {"type": "back-to-work", "workers": workers});
+		
+		this.OrderWalkToRallyPoint(nonWorkers);
+	}
+	else
+		this.OrderWalkToRallyPoint(ejectedEntities);
+	
 	this.UpdateGarrisonFlag();
 
 	return success;
@@ -369,10 +391,10 @@
  * and order them to move to the Rally Point
  * Returns true if all successful, false if not
  */
-GarrisonHolder.prototype.UnloadAll = function(forced)
+GarrisonHolder.prototype.UnloadAll = function(forced, backToWork)
 {
 	var entities = this.entities.slice(0);
-	return this.PerformEject(entities, forced);
+	return this.PerformEject(entities, forced, backToWork);
 };
 
 /**
Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js	(revision 13892)
+++ binaries/data/mods/public/simulation/components/UnitAI.js	(working copy)
@@ -2523,6 +2523,9 @@
 	this.isIdle = false;
 	this.lastFormationName = "";
 	this.finishedOrder = false; // used to find if all formation members finished the order
+	
+	// To go back to work later
+	this.lastWorkOrder = undefined;
 
 	// For preventing increased action rate due to Stop orders or target death.
 	this.lastAttacked = undefined;
@@ -2799,6 +2802,17 @@
 	Engine.PostMessage(this.entity, MT_UnitAIStateChanged, { "to": state });
 };
 
+UnitAI.prototype.BackToWork = function()
+{
+	if(this.lastWorkOrder)
+	{
+		this.ReplaceOrder(this.lastWorkOrder.type, this.lastWorkOrder.data);
+		return true;
+	}
+	else
+		return false;
+};
+
 /**
  * Call when the current order has been completed (or failed).
  * Removes the current order from the queue, and processes the
@@ -2867,6 +2881,9 @@
 {
 	var order = { "type": type, "data": data };
 	this.orderQueue.push(order);
+	
+	if(type == "Gather" || type == "Trade" || type == "Repair")
+		this.lastWorkOrder = order;
 
 	// If we didn't already have an order, then process this new one
 	if (this.orderQueue.length == 1)
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js	(revision 13892)
+++ binaries/data/mods/public/simulation/helpers/Commands.js	(working copy)
@@ -386,10 +386,30 @@
 		for each (var garrisonHolder in entities)
 		{
 			var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
-			if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAll())
+			if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAll(false, false))
 				notifyUnloadFailure(player, garrisonHolder)
 		}
 		break;
+		
+	case "back-to-work":
+		var entities = FilterEntityList(cmd.workers, player, controlAllUnits);
+		for each (var worker in entities)
+		{
+			var cmpUnitAI = Engine.QueryInterface(worker, IID_UnitAI);
+			if (!cmpUnitAI || !cmpUnitAI.BackToWork())
+				notifyBackToWorkFailure(player, worker)
+		}
+		break;
+	
+	case "unload-all-back-to-work":
+		var entities = FilterEntityList(cmd.garrisonHolders, player, controlAllUnits);
+		for each (var garrisonHolder in entities)
+		{
+			var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
+			if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAll(false, true))
+				notifyUnloadFailure(player, garrisonHolder)
+		}
+		break;
 
 	case "formation":
 		GetFormationUnitAIs(entities, player, cmd.name).forEach(function(cmpUnitAI) {
@@ -518,6 +538,17 @@
 }
 
 /**
+ * Sends a GUI notification about worker(s) that failed to go back to work.
+ */
+function notifyBackToWorkFailure(player, worker)
+{
+	var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
+	var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Some unit(s) can't go back to work" };
+	var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+	cmpGUIInterface.PushNotification(notification);
+}
+
+/**
  * Get some information about the formations used by entities.
  * The entities must have a UnitAI component.
  */
