git commit --amend в отсоединенном состоянии HEAD

Я понимаю, что правильный способ внесения изменений в старый коммит GIT — использовать rebase --interactive, но просто для того, чтобы разобраться в концепциях, я хотел бы понять, что происходит, когда я делаю

  • git checkout <commit>
  • изменить что-то в файле
  • добавить измененный файл в индекс
  • а потом git commit . --amend

Когда я это делаю, вместо изменения коммита он разветвляет новый коммит от PARENT того же самого коммита.

Это просто способ GIT сказать мне, что я не могу изменить фиксацию, в которой уже есть дочерние коммиты?


person Chris    schedule 20.09.2014    source источник


Ответы (1)


В Git после создания фиксации она закрепляется; вы не можете его изменить. Все, что вы можете сделать — изменить его, выбрать вишни и т. д. — это создать новый коммит, который будет похож на него.

Я понимаю ваше замешательство: слово «исправить» немного неправильно; это несколько вводит в заблуждение, так как предлагает что-то изменить на месте. В Git изменение коммита на самом деле состоит в создании совершенно нового коммита с теми же родителями, что и исходный коммит.

В качестве примера предположим, что после запуска git checkout B вы оказались в следующей ситуации:

введите здесь описание изображения

(Ваш HEAD отсоединен, но это не относится к делу.) Независимо от того, вносите ли вы изменения и поэтапно или нет, запуск git commit --amend поставит вас в следующую ситуацию:

введите здесь описание изображения

Коммит D может быть очень, очень похож на B; в частности, он может иметь точно такой же патч, точно такое же сообщение коммита, что и B, и т. д. Однако временные метки (коммит, автор) обычно отличаются (если вы не можете изменить фиксацию менее чем за секунду!), что означает SHA -1 из D будет отличаться от B; и если два коммита не имеют одного и того же SHA, они не являются одним и тем же коммитом.

Когда мы говорим, что B является родительским коммитом C, мы имеем в виду коммит C ссылается на коммит B по его SHA. Однако коммит C не может ничего узнать о SHA коммита D, поскольку коммит D был создан после C. Следовательно, D не может быть родителем C. Вот почему коммит D идет по касательной и не имеет потомков.


Если вы хотите приземлиться в следующем состоянии,

введите здесь описание изображения

где B' даже немного отличается от B, вы должны использовать git rebase -i, а не git commit --amend.

person jub0bs    schedule 20.09.2014
comment
Потрясающий ответ. Спасибо! Я полностью упустил тот факт, что --amend всегда будет ответвлением родителя HEAD. Теперь, когда я думаю об этом, это имеет смысл. - person Chris; 21.09.2014