Yeah, so I'll spell out the idea I had in mind, which I think also handles cases like yours. I'll do the steps in a monospaced font so I can indent neatly.
You have a map of hexes, some of which are impassable, say because of mountains. Additionally, some hexes may be temporarily impassable, for instance because they're occupied by another unit. You should also decide on a priority system. For instance, maybe bigger units block smaller ones. Or maybe a speed statistic should decide who "got there first". Alternatively, you can use a random number generator to assign priorities each time a conflict occurs.
1. Each unit plans a route. They plan around permanently impassable hexes, but they ignore temporarily impassable ones at this step.
2. Each unit takes one step along their planned route. Temporarily allow each hex to hold any number of units, but do not update anything other than position. For instance, don't draw their new positions to the screen yet.
a. Each unit moves independently of other units, and as above they may take their moves in any order.
3. Check each occupied node for conflicts. There are no doubt ways to optimize the number of nodes you actually need to check, but this is the simplest. A conflict occurs when, after step 2, two units occupy the same hex. Only the highest-priority unit remains in its new hex. The others are moved to the most recent hex they occupied that didn't cause a conflict.
a. Note that a unit getting bounced back may cause a new conflict if another unit moved into its old hex. You may want to handle resolving such conflicts differently so that you don't need to have a memory of each unit's move history. For instance, if the bounced unit also gets bounced out of its original hex too, it might wind up in the nearest unoccupied hex.
b. If a unit gets bounced out of its original hex, it should keep a memory of all the impassable hexes it tried to occupy, so you can't just have them give up after six failures.
4. Each unit that was bounced back marks the hex it tried to move into as impassable until the next round of movement, but only that hex.
5. Each unit that was bounced back plans a route, as in step 1. If there are no moves that get it closer to its goal, it plans to stay in its current hex.
6. Each unit repeats steps 2 through 5 until it successfully moves, until it is adjacent to no passable hexes, or until it decides to stay in its current hex.
a. Because it's possible for a unit that has met one of these conditions to wind up in a conflict with a unit that has been bounced back far enough, it is important not to forget about them entirely yet. You can forget about a unit when it and all units with higher priority than it have met one of these conditions, though, and I'm pretty sure this is guaranteed to terminate eventually.
Pros:
I'm pretty sure this system models your scenario correctly. Whichever unit has lower priority will get bounced back, decide to stay put for one turn, and then begin moving again.
Allows units to trade places if they're heading opposite directions. Each will move into the other's hex, but by the time conflicts are checked for they're already past each other.
Because each unit plans independently, it doesn't need to coordinate with every other unit to know where the others are going to be after moving. This means that large numbers of complicated routing rules don't blow up the computation time.
Because movement success is independent of the order in which moves are made, it avoids the classic Tabletop RPG problem of the thief who's uncatchable if they went before you but who can't escape if they went after (or, alternatively, the stuttering chase where you leave a gap between them if they move in the wrong order but not if they don't). (@jaked122 - this is why priority is necessary, if I've understood your question correctly)
Cons:
Needs a bit more elaboration to handle varied movement speeds - for instance, if one unit moves 2 hexes per turn and the other only 1, the fast one could leapfrog or do some other weird stuff.
Maybe you don't want units to be able to trade places.
Pathological cases with densely-packed maps can make it take a very long time to terminate.
Occasional weirdness, illustrated below.
I bolded that because that can be a serious problem if you predict lots of densely-packed unit formations, but if you don't then I like this approach.
Note that a possible sequence for a given unit is:
1. Move
2. Win a conflict, so stay in new hex
3. Lose a conflict, so get bounced back to starting hex
4. Decide no other profitable move, so try to stay in starting hex
5. Lose a conflict, so get bounced somewhere else
6. Move back to starting hex
7. Win a conflict because the higher-priority unit that bounced it out was, itself, bounced there and so moved out to be replaced by another, lower-priority unit
Assuming it never gets bounced out again, it'll stay there because it successfully moved in steps 6 + 7. A similarly complicated set of events might even clear up its original target hex, but it won't have the move to try and occupy that one - that's the weirdness I was referring to. The probability should be very low, but it is something to be aware of.