Страницы

Поиск по вопросам

среда, 17 октября 2018 г.

Почему `git commit --amend` создает новый коммит?

Исходя из этого лога видно, что есть лишние кометы
* 100ef3f - (HEAD -> master) ss (4 hours ago) * 6392bff - version 1.11 (27 hours ago) | * c740677 - (tag: 1.11) version 1.11 (2 days ago) |/ * bbc79f8 - test one (2 days ago) * 2443876 - -updated gradle version **//** (4 days ago) | * 4ef2ee2 - (tag: 1.10) -updated gradle version **//** (4 days ago) |/ | * 2562070 - (origin/master, origin/HEAD) -updated gradle version **//**. (8 days ago) |/ * 8e2dad6 - -merge. -added ws for **//** (9 days ago) * 1820027 - final commit (9 days ago) * 8b35461 - test commit (9 days ago) * 0d69468 - -changes in **//** . (2 months ago) * 1f12302 - (tag: 1.09) Version 1.09 (3 months ago) * 51cb421 - -added **//** * ad0ecef - -git init. (5 months ago)
Так же изображение только из UI

Так вот есть предположение благодаря @NickVolynkin , что эти коммиты создаются в следствии использования команды git commit --amend
Но насколько я понимаю эта команда должна прибавить текущие изменения в прошлый коммит
Почему создается новый?


Ответ

Потому что коммит неизменяем. Его идентификатор, хэш, зависит от его содержимого. Меняете содержимое — меняется хэш, получается коммит с другим идентификатором, но от того же основания, что и текущий коммит.
Жаловаться на это это примерно как жаловаться на то, что если к 5 прибавить ещё единичку, получится совсем другое число :)
git commit --amend "забывает" про текущий коммит, берёт тот же коммит на котором был основан старый*, делает поверх него* новый коммит, учитывая содержимое индекса** и переносит ветку на получившийся результат. Изменения существующих коммитов реально не происходит.
На самом деле это хорошо. Это избавляет от сюрпризов из серии "где-то что-то неожиданно изменилось". А для системы контроля версий это хорошая черта.
Поэтому существует практика:
никогда не делать commit --amend на опубликованных коммитах***
...а то сами видите, к чему это приводит.

Впрочем, система не идеальна, и недавние новости про взлом SHA-1, который используется внутри Git, было посеяли сомнения, не даёт ли это возможности подделывать хэш каким-нибудь левым изменениям так, чтобы Git ничего не заподозрил.
Беспокоиться об этом пока рано, всем кроме разве что самых крупных ИТ-гигантов. На практике используется ещё и длина данных, что на порядок затрудняет подбор коллизии. А это и без того непросто, практически нереально: на известный случай взлома ушло около 6500 ЦПУ-лет. Нужна крайне серьёзная причина, чтобы выделить такое количество ресурсов на каждую подобную операцию.

* или несколько коммитов, если заменяется коммит слияния
** а там, если что, все отслеживаемые файлы, а не только изменённые, поэтому если ветка внезапно начинает указывать на другой коммит, сравнение с состоянием в индексе (и, как следствие, вычисление изменений для коммитов) по-прежнему работает правильно
*** с кучей "если": скажем, если это не лично ваша ветка, на которую никто кроме вас рассчитывать не собирается, а если собирается, то сам виноват; хороший пример это фича-ветки их разнообразных Git*-flow.

Комментариев нет:

Отправить комментарий