git reset
по умолчанию --mixed
, и он действительно отменяет коммиты, сохраняя изменения в локальном дереве («измененные файлы сохраняются, но не помечаются для фиксации»).
Что касается ревизии. В то время как в описанном вами сценарии вы получите такое же поведение, вы, вероятно, захотите сказать: HEAD~
и запустить его дважды ... или еще лучше HEAD~~
или просто HEAD~2
.
Это не редкость источник путаницы, но вкратце:
~
проходит через поколения (глубже по линии первых родителей) ^
проходит через родителей предыдущего поколения (мнемони c: окружность выглядит как небольшая развилка, вы можете посещать узлы, где развивается история).
Пока вы используете их без каких-либо чисел, вы всегда получаете крайнего левого предка с каждым прыжком, поэтому HEAD~~~
и HEAD^^^
приведет вас к тому же месту, HEAD~2
(два крайних левых родителя сзади) не совпадают с HEAD^2
(вторым от левого родителя).
Более подробную информацию можно найти в git rev-parse
описание, включая визуальную иллюстрацию:
Вот иллюстрация Джона Лоулигера. Оба узла фиксации B и C являются родителями узла фиксации A. Родительские коммиты располагаются слева направо.
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
A
A = = A^0
B = A^ = A^1 = A~1
C = A^2 = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2 = B^^2 = A^^^2 = A~2^2
I = F^ = B^3^ = A^^3^
J = F^2 = B^3^2 = A^^3^2
Кроме того, если вы обеспокоены выполнением действия, вы можете всегда выполняйте ветвление (например, git checkout -b temp
), попробуйте выполнить команду, а при удачном переключении назад удалите временную ветвь и выполните ее там.