Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(revision 13955)
+++ 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 && state.unitAI && state.unitAI.lastWorkOrder)
+			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 13955)
+++ binaries/data/mods/public/gui/session/utility_functions.js	(working copy)
@@ -293,6 +293,24 @@
 		    "icon": "focus-rally.png"
 		});
 	}
+	
+	if (entState.unitAI && entState.unitAI.lastWorkOrder)
+	{
+		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 13955)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(working copy)
@@ -261,9 +261,10 @@
 
 /**
  * Ejects units and orders them to move to the Rally Point.
+ * If backToWork is set to true, ejects units, order the ones who can go back to work to do so, and the others 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 +284,28 @@
 			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 cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI);
+		if (cmpUnitAI && cmpUnitAI.GetLastWorkOrder())
+			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/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(revision 13955)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -348,6 +348,7 @@
 		ret.unitAI = {
 			"state": cmpUnitAI.GetCurrentState(),
 			"orders": cmpUnitAI.GetOrders(),
+			"lastWorkOrder": cmpUnitAI.GetLastWorkOrder(),
 		};
 		// Add some information needed for ungarrisoning
 		if (cmpUnitAI.isGarrisoned && ret.player !== undefined)
Index: binaries/data/mods/public/simulation/components/Promotion.js
===================================================================
--- binaries/data/mods/public/simulation/components/Promotion.js	(revision 13955)
+++ binaries/data/mods/public/simulation/components/Promotion.js	(working copy)
@@ -78,6 +78,8 @@
 	cmpPromotedUnitAI.Cheer();
 	var orders = cmpCurrentUnitAI.GetOrders();
 	cmpPromotedUnitAI.AddOrders(orders);
+	var lastWorkOrder = cmpCurrentUnitAI.GetLastWorkOrder();
+	cmpPromotedUnitAI.SetLastWorkOrder(lastWorkOrder);
 
 	Engine.BroadcastMessage(MT_EntityRenamed, { entity: this.entity, newentity: promotedUnitEntity });
 
Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js	(revision 13955)
+++ binaries/data/mods/public/simulation/components/UnitAI.js	(working copy)
@@ -2525,6 +2525,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;
@@ -2801,6 +2804,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
@@ -2817,8 +2831,17 @@
 		error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack);
 	}
 
-	this.orderQueue.shift();
+	// Remove the order from the queue, then forget it if it was a work to avoid trying to go back to it later.
+	var finishedOrder = this.orderQueue.shift();
+	if(finishedOrder.type == "Gather" || finishedOrder.type == "Trade" || finishedOrder.type == "Repair")
+		this.lastWorkOrder = undefined;
+	
 	this.order = this.orderQueue[0];
+	// If the worker was returning a resource, we shall 
+	//	-> (if the worker is gathering) keep remembering the "Gather" order which is this.order
+	//	-> (if the worker was directly ordered to return a resource) forget the "ReturnResource" order which is finished
+	if(finishedOrder.type == "ReturnResource" && (!this.order || this.order.type != "Gather"))
+		this.lastWorkOrder = undefined;
 
 	if (this.orderQueue.length)
 	{
@@ -2869,6 +2892,9 @@
 {
 	var order = { "type": type, "data": data };
 	this.orderQueue.push(order);
+	
+	if(type == "Gather" || type == "Trade" || type == "Repair" || type == "ReturnResource")
+		this.lastWorkOrder = order;
 
 	// If we didn't already have an order, then process this new one
 	if (this.orderQueue.length == 1)
@@ -2972,6 +2998,16 @@
 	return orders;
 };
 
+UnitAI.prototype.GetLastWorkOrder = function()
+{
+	return this.lastWorkOrder;
+};
+
+UnitAI.prototype.SetLastWorkOrder = function(order)
+{
+	this.lastWorkOrder = order;
+};
+
 UnitAI.prototype.TimerHandler = function(data, lateness)
 {
 	// Reset the timer
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js	(revision 13955)
+++ 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.
  */
