Когда вы уже хорошо знакомы с командами add, commit, pull и push, наступает момент, когда нужно больше. Не просто сохранять изменения, а управлять историей. И здесь Git предлагает команды, которые могут быть как полезными, так и опасными.
Rebase:
Rebase нужен, когда вы работаете над своей веткой, а в основной ветке (например main) за это время появились новые коммиты и вы хотите, чтобы ваша ветка строилась поверх этих новых изменений из основной ветки.
После git rebase main коммиты D и E превращаются в D' и E' с другими хэшами. Пока ветка только ваша, все безопасно. Если на ней уже работают другие - у них все разъедется.
Это главное правило: rebase можно делать на своих ветках, но не на общих. Если вы переписали историю, а коллеги уже забрали ваши коммиты, у них все сломается.
После rebase обычный push не пройдет - вы получите rejected (non-fast-forward). Есть два способа это исправить:
🔹Первый: git push --force. Он перезапишет удаленную ветку вашей версией. Если кто-то успел запушить свои изменения, они будут потеряны.
🔹Второй: git push --force-with-lease. Он безопаснее: пуш пройдет, только если удаленная ветка не менялась с последнего fetch. Иначе Git откажет, и чужая работа уцелеет.
Amend - исправление последнего коммита:
Amend нужен, чтобы изменить последний коммит. Это удобно, когда вы забыли добавить файл, допустили опечатку в сообщении или хотите объединить изменения с предыдущим коммитом.
Например вы закоммитили изменения, а потом вспомнили, что забыли файл:
git add forgotten-file.ts
git commit --amend --no-edit
Флаг --no-edit означает, что сообщение коммита останется прежним. Если нужно изменить и его, уберите этот флаг - Git откроет редактор.
Важно понимать: amend не редактирует существующий коммит. Он создает новый с тем же содержимым, но другим хэшем. Если ветка уже на удаленном сервере, обычный push не пройдет - вы получите rejected (non-fast-forward).
В этом случае есть два варианта:
🔹Первый: git push --force. Он перезапишет удаленную ветку вашей версией. Если кто-то успел запушить свои изменения, они будут потеряны.
🔹Второй: git push --force-with-lease. Он безопаснее: пуш пройдет, только если удаленная ветка не менялась с последнего fetch. Иначе Git откажет, и чужая работа уцелеет.
Reset - откат назад:
Reset нужен, чтобы откатиться назад по истории коммитов. Но важно знать, что происходит с изменениями:
🔹git reset --soft HEAD~1: откатывает коммит, но оставляет изменения в индексе. Можно сразу закоммитить заново.
🔹git reset --mixed HEAD~1: откатывает коммит, но оставляет изменения в рабочей папке без индексации. Нужно снова делать add.
🔹git reset --hard HEAD~1: стирает изменения и из индекса, и из рабочей папки. Использовать с осторожностью, потому что данные исчезают.
Reflog - восстановление потерянных коммитов:
Reflog нужен, чтобы найти коммиты, которые исчезли из видимой истории. git log показывает коммиты, доступные в той части истории, которую вы просматриваете в данный момент.
Если вы откатите ветку назад, некоторые коммиты могут исчезнуть из вывода git log. Однако это не обязательно означает, что Git тут же их удалил. Git также ведет локальный журнал перемещений ссылок (например HEAD), поэтому исчезнувший коммит может быть в reflog. Вы можете просмотреть его с помощью:
git reflog
Вы можете увидеть что-то подобное:
e35fa12 HEAD@{0}: reset: moving to HEAD~2
821cd77 HEAD@{1}: commit: Add authentication
f992ab1 HEAD@{2}: commit: Add login page
Вот ваш недостающий коммит. Теперь вы можете переместить ветку обратно к этому коммиту:
git reset --hard 821cd77
🔗 Читать подробнее
💡 Вывод:
Git - это инструмент, который дает много возможностей. Но с возможностями приходит ответственность. Rebase, amend, reset и force - мощные команды, которые могут изменить историю. Использовать их нужно с умом.
Если ветка только ваша - можно делать что угодно. Если на ней работают другие - лучше использовать revert и force-with-lease. А если что-то потеряли - reflog поможет.
Подписаться на канал:
➡️ Кот Денисова