Если вы указали опцию --mixed, выполнение reset остановится на этом шаге. Такое поведение также используется по умолчанию, поэтому если вы не указали совсем никаких опций (в нашем случае git reset HEAD~), выполнение команды также остановится на этом шаге.
Снова взгляните на диаграмму и постарайтесь разобраться, что произошло: отменен не только ваш последний commit, но также и добавление в индекс всех файлов. Вы откатились назад до момента выполнения команд git add и git commit.
Шаг 3: Обновление Рабочего Каталога (--hard)
Третье, что сделает reset – это приведение вашего Рабочего Каталога к тому же виду, что и Индекс. Если вы используете опцию --hard, то выполнение команды будет продолжено до этого шага.

Давайте разберемся, что сейчас случилось. Вы отменили ваш последний коммит, результаты выполнения команд git add и git commit, а также всеизменения, которые вы сделали в рабочем каталоге.
Важно отметить, что только указание этого флага (--hard) делает команду reset опасной, это один из немногих случаев, когда Git действительно удаляет данные. Все остальные вызовы reset легко отменить, но при указании опции --hard команда принудительно перезаписывает файлы в Рабочем Каталоге. В данном конкретном случае, версия v3нашего файла всё еще остается в коммите внутри базы данных Git и мы можем вернуть ее, просматривая наш reflog, но если вы не коммитили эту версию, Git перезапишет файл и ее уже нельзя будет восстановить.
Команда reset в заранее определенном порядке перезаписывает три дерева Git, останавливаясь тогда, когда вы ей скажете:
1. Перемещает ветку, на которую указывает HEAD (останавливается на этом, если указана опция --soft)
2. Делает Индекс таким же как и HEAD (останавливается на этом, если не указана опция --hard)
3. Делает Рабочий Каталог таким же как и Индекс.
Основной форме команды reset (без опций --soft и --hard) вы также можете передавать путь, с которым она будет оперировать. В этом случае, reset пропустит первый шаг, а на остальных будет работать только с указанным файлом или набором файлов. Первый шаг пропускается, так как HEAD является указателем и не может ссылаться частично на один коммит, а частично на другой. Но Индекс и Рабочий Каталог могут быть изменены частично, поэтому reset выполняет шаги 2 и 3.
Итак, предположим вы выполнили команду git reset file.txt. Эта форма записи (так как вы не указали ни SHA-1 коммита, ни ветку, ни опций --soft или --hard) является сокращением для git reset --mixed HEAD file.txt, которая:
1. Перемещает ветку, на которую указывает HEAD (будет пропущено)
2. Делает Индекс таким же как и HEAD (остановится здесь)
То есть, фактически, она копирует файл file.txt из HEAD в Индекс.

Это создает эффект отмены индексации файла. Если вы посмотрите на диаграммы этой команды и команды git add, то увидите, что их действия прямо противоположные.

Именно поэтому в выводе git status предлагается использовать такую команду для отмены индексации файла. (Смотрите подробности в Отмена подготовки файла.)
Мы легко можем заставить Git “брать данные не из HEAD”, указав коммит, из которого нужно взять версию этого файла. Для этого мы должны выполнить следующее git reset eb43bf file.txt.

Можно считать, что, фактически, мы в Рабочем Каталоге вернули содержимое файла к версии v1, выполнили для него git add, а затем вернули содержимое обратно к версии v3(в действительности все эти шаги не выполняются). Если сейчас мы выполним git commit, то будут сохранены изменения, которые возвращают файл к версии v1, но при этом файл в Рабочем Каталоге никогда не возвращался к такой версии.
Заметим, что как и команде git add, reset можно указывать опцию --patch для отмены индексации части содержимого. Таким способом вы можете избирательно отменять индексацию или откатывать изменения.
Давайте посмотрим, как, используя вышеизложенное, сделать кое-что интересное – слияние коммитов.
Читать дальше