Олег Марков
Изменение последнего коммита в Git с помощью git commit --amend
Введение
Команда git commit --amend — один из самых полезных инструментов Git, когда нужно быстро поправить только что сделанный коммит. Вы могли:
- забыть добавить файл;
- допустить опечатку в сообщении;
- случайно закоммитить лишние изменения;
- изменить код после ревью и хотите обновить тот же коммит.
С помощью git commit --amend вы можете изменить последний коммит так, будто он всегда был именно таким. Смотрите, я покажу вам, как это работает, какие есть подводные камни и в каких ситуациях amend использовать безопасно, а где лучше не трогать историю.
Дальше мы подробно разберем:
- что именно делает git commit --amend;
- как изменить только сообщение последнего коммита;
- как добавить или убрать файлы в последнем коммите;
- как работать с amend в связке с push и удаленными ветками;
- как отменить неудачный amend;
- как настроить удобную работу с редактором.
Что такое git commit --amend и как он работает
Краткая идея
Команда git commit --amend не “редактирует” существующий коммит буквально. Она создает новый коммит, который:
- основан на том же родителе, что и предыдущий;
- содержит измененный набор файлов и/или новое сообщение;
- полностью заменяет собой предыдущий коммит в текущей ветке.
То есть последний коммит фактически переписывается. Старый коммит остается в истории репозитория, но ветка на него больше не ссылается.
Как Git видит это изнутри
Представьте, что у вас есть история:
- Коммит A (старый)
- Коммит B (последний, HEAD указывает на него)
Когда вы запускаете:
git commit --amend
Git:
- Берет родителя коммита B (то есть A).
- Берет текущее состояние индексированных файлов (staging area).
- Создает новый коммит C с родителем A.
- Переносит указатель ветки (например, main или feature) с B на C.
- Ставит HEAD на C.
Коммит B остается “висящим”, пока его окончательно не уберет сборщик мусора. Но с точки зрения обычной истории вы его больше не увидите.
Важный вывод
Amend — это переписывание истории. Это безопасно, пока вы работаете только локально или с коммитами, которые еще не были отправлены в общий репозиторий. Как только измененный коммит уже ушел в удаленный репозиторий и другие разработчики могли его забрать, amend нужно применять очень осторожно.
Изменение только сообщения последнего коммита
Частая ситуация: код вас устраивает, но сообщение получилось неудачным — слишком коротким, непонятным или с опечаткой. Давайте разберемся, как поправить только сообщение, не трогая содержимое файлов.
Базовый вызов
Если вы хотите изменить только текст сообщения, при этом файлы не менять, убедитесь, что индекс пустой:
git status
Вы должны увидеть что-то вроде:
nothing to commit, working tree clean
Теперь меняем сообщение:
git commit --amend
Откроется редактор сообщений коммита (по умолчанию чаще всего Vim или Nano). Там вы увидите старое сообщение, которое можно отредактировать.
Например, было:
fix
Вы меняете на:
Исправлен баг с авторизацией при пустом пароле
Смотрите, какой здесь важный момент: Git возьмет текущее состояние индекса. Если перед amend вы что-то добавите в индекс (git add), эти изменения войдут в новый коммит, даже если вы лишь хотели изменить сообщение. Поэтому всегда проверяйте статус перед amend.
Изменение сообщения без открытия редактора
Если вы хотите задать сообщение прямо в командной строке:
git commit --amend -m "Более понятное сообщение о коммите"
Здесь:
- флаг -m задает новое сообщение;
- редактор не откроется;
- содержимое коммита останется прежним, если вы не меняли индекс.
Пример:
// Исправляем неудачное сообщение последнего коммита
git commit --amend -m "Добавлена проверка прав при удалении пользователя"
Как проверить результат
После amend удобно посмотреть историю:
git log -1
Команда показывает только последний коммит. Вы увидите новое сообщение и новый хеш. Старый хеш пропал из основной истории.
Добавление забытых файлов в последний коммит
Теперь давайте разберемся с самой популярной ситуацией: вы сделали commit, а потом поняли, что забыли добавить один или несколько файлов.
Типичный сценарий
- Вы изменили несколько файлов.
Добавили часть в индекс:
git add file1.jsЗакоммитили:
git commit -m "Добавлены новые обработчики событий"Потом заметили, что пропустили file2.js.
Чтобы не создавать новый “исправляющий” коммит, можно просто доработать предыдущий:
// Добавляем забытый файл в индекс
git add file2.js
// Перезаписываем последний коммит, добавляя file2.js
git commit --amend
Откроется редактор сообщения:
- можете оставить прежнее сообщение;
- можете скорректировать его так, чтобы оно отражало полный набор изменений.
Например, измените:
Добавлены новые обработчики событий
на:
Добавлены новые обработчики событий и логирование ошибок
Теперь один коммит аккуратно содержит все необходимые изменения.
Изменение коммита без редактирования сообщения
Если вы хотите только добавить файлы, а сообщение оставить прежним, можно сделать так:
git add file2.js
git commit --amend --no-edit
Флаг --no-edit говорит Git: “оставь сообщение как есть”.
Добавление нескольких файлов
Никакой разницы нет — вы можете добавить сразу несколько файлов:
git add file2.js file3.js styles.css
git commit --amend --no-edit
Или добавить все измененные файлы:
git add .
git commit --amend --no-edit
Здесь я специально использую add . только как пример, но в реальных проектах лучше явно указывать файлы, чтобы не включить случайные изменения.
Удаление лишних файлов из последнего коммита
Иногда в последний коммит “заезжают” файлы, которые не должны были попадать в репозиторий:
- временные файлы IDE;
- локальные настройки;
- тестовые скрипты;
- крупные артефакты сборки.
Давайте разберемся, как убрать их из последнего коммита.
Шаг 1. Извлечь файлы из индекса
Предположим, вы случайно включили файл debug.log. Чтобы удалить его из последнего коммита, но оставить в рабочем каталоге:
// Убираем файл из индекса, но оставляем на диске
git reset HEAD debug.log
Комментарий:
// Эта команда снимает файл с индекса и готовит его к исключению из нового коммита
Если вы хотите совсем удалить файл из рабочего каталога и из коммита:
// Удаляем файл с диска и помечаем на удаление в коммите
git rm debug.log
Шаг 2. Пересобрать последний коммит
После того как индекс настроен так, как нужно (лишние файлы убраны или помечены на удаление), выполняем:
git commit --amend
Или, если сообщение не нужно менять:
git commit --amend --no-edit
Пример на нескольких файлах
Допустим, вы случайно закоммитили:
- debug.log
- node_modules/some-cache-file
Покажу вам, как это исправить:
// Убираем debug.log из индекса, но не удаляем его с диска
git reset HEAD debug.log
// Удаляем проблемный файл из node_modules полностью
git rm node_modules/some-cache-file
// Переписываем последний коммит без этих файлов
git commit --amend --no-edit
После этого новый последний коммит не содержит этих файлов.
Amend и удаленные репозитории: push, force-push и риски
Что происходит после amend и push
Если вы уже отправили коммит в удаленный репозиторий (например, на GitHub или GitLab), а затем сделали amend, у вас появляются два разных коммита:
- старый коммит — в удаленном репозитории;
- новый коммит — в локальной ветке.
Git считает, что история “разошлась”. При попытке обычного push вы увидите сообщение вида:
To origin main
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'git@github.com:user/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
Как выровнять истории с помощью force-push
Чтобы заменить историю в удаленном репозитории новой версией, нужно использовать принудительную отправку:
// Переписываем историю удаленной ветки согласно локальной
git push --force
Или более безопасный вариант:
git push --force-with-lease
Комментарий:
// --force-with-lease отправляет изменения только если удаленная ветка не была // изменена кем-то еще с тех пор как вы ее последний раз получали
Когда force-push допустим
Force-push (и, соответственно, amend уже отправленных коммитов) обычно допустим:
- в вашей личной ветке, которой никто больше не пользуется;
- в feature-ветке до того, как она была влита в основную ветку;
- в ранних стадиях разработки, когда договоренность в команде разрешает переписывать историю.
Когда лучше не использовать amend после push
Старайтесь избегать amend и force-push, если:
- вы работаете в общей ветке (например, main, develop) и другие разработчики активно в нее коммитят;
- ваш коммит уже кто-то забрал, начал на нем работу или сделал на его основе свои коммиты.
В таких случаях лучше:
- создать новый “исправляющий” коммит (например, с сообщением “Fix config error from previous commit”);
- не трогать историю уже расшаренных коммитов.
Практические сценарии применения git commit --amend
Сценарий 1. Быстрая правка описания без изменения кода
Вы сделали коммит:
git commit -m "stuff"
Потом замечаете, что сообщение бесполезное. Давайте поправим:
// Проверяем состояние
git status
// Переписываем сообщение
git commit --amend -m "Реализован поиск по email и логину в API пользователей"
Результат:
- код в коммите тот же;
- сообщение стало осмысленным и понятным ревьюерам.
Сценарий 2. Добавили тесты после основного изменения
Вы сначала реализовали функциональность, закоммитили ее, а потом написали тесты. Чтобы история выглядела аккуратной:
// Пишем и добавляем тесты
git add user_search_test.go
// Обновляем последний коммит, добавляя тесты
git commit --amend -m "Реализован поиск пользователей и добавлены тесты"
Как видите, такой подход позволяет сделать один атомарный коммит, где и код, и тесты — в одном месте. Это упрощает ревью и понимание истории.
Сценарий 3. Удаление секретов из последнего коммита
Бывает, что вы случайно закоммитили:
- пароль;
- токен;
- ключ API.
Если это только в последнем коммите и вы не успели его отправить в удаленный репозиторий, достаточно:
// Убираем секреты из кода и конфигов
// Например, редактируем config.json, удаляя токен
// Добавляем исправленный конфиг
git add config.json
// Перезаписываем последний коммит
git commit --amend -m "Настройки без секретов - токен перемещен в переменные окружения"
Если же секрет уже ушел в удаленный репозиторий, проблема серьезнее: его нужно считать скомпрометированным, изменить ключ и уже потом чистить историю (часто с помощью git filter-repo). Но amend в таком случае помогает только локально.
Сценарий 4. Объединение “мусорного” коммита с основным
Иногда вы делаете такой набор действий:
git commit -m "Основная реализация авторизации"
git commit -am "Мелкие правки форматирования"
Второй коммит “мусорный” и логичнее слить его в первый, чтобы история была чище. Вы можете использовать rebase interactive, но если это последний коммит — проще amend.
Смотрите, как можно сделать:
Откатиться к предыдущему коммиту, но оставить изменения в рабочем каталоге:
git reset --soft HEAD~1Комментарий:
// Сдвигаем HEAD на один коммит назад, но не трогаем файлы — все изменения остаются в индексе
Теперь в индексе есть изменения из двух коммитов. Создаем новый, аккуратный:
git commit --amend -m "Основная реализация авторизации и правки форматирования"
В итоге у вас один содержательный коммит вместо двух.
Безопасность и откат после git commit --amend
Как отменить amend сразу после него
Если вы только что сделали amend и поняли, что зря:
Посмотрите лог с ссылками:
git reflogПример вывода:
a1b2c3d HEAD@{0}: commit (amend): Исправлен баг авторизации 9f8e7d6 HEAD@{1}: commit: Исправлен баг авторизацииЗдесь:
- HEAD@{0} — текущий amend-commit;
- HEAD@{1} — предыдущий коммит, который вы только что переписали.
Верните указатель ветки на старый коммит:
// Возвращаемся к состоянию до amend git reset --hard HEAD@{1}
Комментарий:
// reset --hard меняет и историю, и рабочий каталог — несохраненные изменения будут потеряны
Если amend уже отправлен в удаленный репозиторий
Ситуация сложнее, особенно если кто-то уже забрал изменения. Общий принцип:
- если вы единственный, кто использует ветку, можно вернуть историю через reset и снова сделать force-push;
- если ветка общая, нужно координироваться с командой.
Пример, когда вы одни в ветке:
// Находим коммит до amend
git reflog
// Возвращаем ветку к нему
git reset --hard <old-commit-hash>
// Перезаписываем удаленную ветку
git push --force-with-lease
Настройка редактора для git commit --amend
Когда вы вызываете git commit --amend без -m, Git открывает редактор для изменения сообщения. Часто это Vim по умолчанию, который не всем удобен.
Проверка текущего редактора
git config --global core.editor
Если ничего не выводится, используется редактор по умолчанию системы (часто Vim).
Установка удобного редактора
Например, если вы хотите использовать Nano:
git config --global core.editor "nano"
Комментарий:
// Теперь при вызове git commit --amend будет открываться Nano для редактирования сообщения
Если вы работаете в VS Code:
git config --global core.editor "code --wait"
Флаг --wait говорит VS Code дождаться закрытия окна редактирования, прежде чем Git продолжит выполнение команды.
Теперь, когда вы запускаете:
git commit --amend
сообщение откроется в выбранном вами редакторе.
Советы по хорошему стилю при использовании git commit --amend
Делайте коммиты атомарными
Старайтесь, чтобы один коммит решал одну логическую задачу: исправление бага, добавление фичи, рефакторинг. Amend отлично помогает поддерживать такой стиль, когда вы:
- добавляете забытые тесты;
- дописываете небольшие части кода;
- поправляете форматирование в рамках того же изменения.
Не бойтесь переписывать локальную историю
Пока вы не сделали push, amend — ваш лучший друг:
- неудачное сообщение — поправили;
- забыли файл — добавили;
- случайно включили лишний — убрали.
Локальная история — ваша рабочая зона, и amend помогает держать ее чистой еще до того, как кто-то увидит ваши коммиты.
Но будьте осторожны с общими ветками
Основное правило:
- до push — amend сколько угодно;
- после push в общую ветку — amend только в крайних случаях и с пониманием последствий.
Если сомневаетесь, проще создать новый коммит с корректировкой, чем переписывать историю, которую уже могут использовать другие.
Ответы на частозадаваемые технические вопросы
Как изменить не последний, а предпоследний или более ранний коммит?
Для этого одного git commit --amend недостаточно. Используйте интерактивный rebase:
// Откатываемся на 3 коммита назад в режиме rebase
git rebase -i HEAD~3
В открывшемся списке коммитов:
- Замените слово
pickрядом с нужным коммитом наedit. - Сохраните файл и закройте редактор.
- Когда rebase остановится на редактируемом коммите, измените файлы и/или сообщение:
bash git commit --amend - Затем продолжите rebase:
bash git rebase --continue
Так вы можете точечно править более старые коммиты.
Что делать, если я сделал git commit --amend на неправильной ветке?
Найдите хеш старого коммита через reflog:
git reflogПереключитесь на нужную ветку (если нужно — создайте ее):
git checkout правильная-веткаПеренесите коммит или верните его командой cherry-pick:
git cherry-pick <commit-hash>Если в текущей ветке amend-commit не нужен, верните историю назад:
git reset --hard HEAD@{1}
Как изменить автора последнего коммита с помощью amend?
Вы можете указать автора явно:
git commit --amend --author="Имя Фамилия <email@example.com>"
Если хотите также открыть редактор для изменения сообщения, просто не добавляйте -m:
git commit --amend --author="Имя Фамилия <email@example.com>"
Автор будет обновлен, коммит получит новый хеш.
Можно ли использовать git commit --amend при работе с подписью коммитов (GPG или SSH)?
Да, но каждый новый коммит (включая amend) нужно подписывать заново. Если у вас включена авто-подпись:
git config --global commit.gpgsign true
то при выполнении:
git commit --amend
Git автоматически подпишет новый коммит. Если подпись не происходит, проверьте настройки GPG/SSH и наличие нужных ключей.
Как увидеть, что именно изменилось между старым и новым коммитом после amend?
Если вы помните хеш старого коммита, можно сравнить содержимое:
git diff <old-hash> <new-hash>
Если не помните, найдите оба через reflog:
git reflog
Затем запустите diff между ними. Так вы увидите, какие файлы и строки изменились после amend и сможете проверить, что в новый коммит попало именно то, что нужно.
Постройте личный план изучения Git до уровня Middle — бесплатно!
Git — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Git
Лучшие курсы по теме

Основы Git
Антон Ларичев
TypeScript с нуля
Антон Ларичев