Here is an attempt to explain the issue in a more graphical way.
$ echo 1 > a && echo 2 > b
$ vim -d a b
a is the current buffer:
+--------+--------+
| 1 | 2 |
| | |
| | |
| | |
+-[a]----+--b-----+
b is the target of dp so, after dp, the current buffer is unchanged and u is useless. It is the target that is changed and you can't undo a change in one buffer from another one:
+--------+--------+
| 1 | 1 |
| == dp => |
| | |
| | |
+-[a]----+--b*----+
b must become current for u to work:
+--------+--------+
| 1 | 1 |
| | |
| | |
| | |
+--a-----+-[b]*---+ do <C-w>w to change window
after u:
+--------+--------+
| 1 | 2 |
| | |
| | |
| | |
+--a-----+-[b]----+
Now, let's go back to the beginning, with a being current:
+--------+--------+
| 1 | 2 |
| | |
| | |
| | |
+-[a]----+--b-----+
After do, it is the current buffer that is changed:
+--------+--------+
| 2 | 1 |
| <= do == |
| | |
| | |
+-[a]*---+--b-----+
and the change can be undone with u without having to change windows:
+--------+--------+
| 1 | 2 |
| | |
| | |
| | |
+-[a]----+--b-----+
u? With two buffers "a" and "b", and "a" is the current one, doingdpchanges "b", not "a", so the change must be undone from "b". With the same setup,dochanges "a" souworks in "a" but not in "b".