Каким образом git commit -amend работает, точно?

Я видел GIT commit --amend в отдельном состоянии HEAD. Вопрос требует, чтобы ответ был более сложным, чем нужно. Я хотел бы понять, как git commit --amend работает в нормальной ситуации с HEAD.

Ответ 1

Предположим, что вы находитесь в чистом рабочем состоянии и что ваше репо выглядит следующим образом:

enter image description here

Если вы запустите

git commit --amend

записать сообщение о фиксации, сохранить и закрыть редактор, произойдет следующее:

  • Ваша промежуточная область, которая, если вы не устроили никаких новых изменений, будет идентична commit f42c5 - используется для создания нового фиксации: 31b8e. Его родитель будет таким же, как и те (те) комманды, которую вы исправляете: f42c5.
  • Ссылка на ветку master перемещается, чтобы указать на новый фиксатор (31b8e).
  • Ссылка HEAD следует master.

enter image description here

Обратите внимание, что исправленная фиксация (f42c5) теперь недоступна из любой ссылки в вашем репо (отсюда ее "прозрачный" стиль на моем графике). Он по-прежнему живет в базе данных объектов репозитория, но в конечном итоге удаляется навсегда, когда Git запускает периодическое ведение домашнего хозяйства, или если вы запускаете его явно, запустив git gc (сбор мусора).


Добавление (на основе комментарий Джейсона Бейкера): Обратите внимание, что до тех пор, пока исправленное коммит, f42c5, все еще существует в ваше репо, и у вас есть способ узнать его идентификатор фиксации (например, вытащив его из ветки master reflog), вы все равно можете его проверить. Запуск

git checkout master # just to be sure that master is the current branch
git reset --hard f42c5

или (предположив, что вы еще не сделали никаких новых фиксаций на master, reset master или иначе переместили ссылку на master)

git checkout master # just to be sure that master is the current branch
git reset --hard [email protected]{1}

поставит вас в следующую ситуацию:

enter image description here

Но теперь commit 31b8e станет недоступным.


Ответ 2

Скажите, что вы только что сделали "B"

... --- A --- B
              ^
              |
            master
             HEAD

Изменение "B" создаст параллельную фиксацию, которая станет новой ветвью ветки.

        +---- B
        |
... --- A --- B'
              ^
              |
            master
             HEAD

B '- это фиксация, полученная из комбинации изменений из B плюс изменения, которые вы поставили, когда вы выпустили git commit --amend.

Ответ 3

По моим сведениям, ammend работает таким образом:

В случае git commit --ammend изменения изменений в амперметре должны быть в области Stagging (SA)

  • Он делает git reset -- soft для возврата изменений, внесенных в последний коммит (commit to amend) в SA, и переводит индекс в предыдущее commit (commit перед фиксацией для изменения). Все хранится, как было до использования команды git commit.
  • Он делает git add со всеми файлами, которые нужно добавить к новому фиксации (это будет исправленная фиксация). Добавляемые файлы находятся в SA до того, как git reset --soft был приземлен, после reset эти файлы попадают в WD, поэтому необходимо добавить их в SA для генерации исправленного коммита.
  • Делает git commit. Он будет генерировать новую фиксацию и, следовательно, новый идентификатор для исправленного коммита. Для этого git commit -ammend не следует использовать с нажатыми коммитами

Если вы используете --no-edit, комментарий повторно используется в исправленном коммите, иначе вы должны ввести новый комментарий (потому что это новый коммит, и каждый коммит требует комментария).

Для получения дополнительной информации о области оцепенения и рабочем каталоге см. Reset Demystified