Поиск по сайту:

Как исправить, изменить или отменить коммиты Git (изменение истории Git)


История коммитов Git разработана так, чтобы быть неизменной (по большей части) и отслеживать каждое изменение в вашем проекте, чтобы вы никогда не теряли работу. Однако иногда необходимо переписать историю Git, поэтому Git предоставляет несколько инструментов для редактирования существующих коммитов.

Добавление новых изменений в коммиты

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

Если вы просто добавляете изменения, вы можете использовать git commit --amend. Это изменяет самую последнюю фиксацию и объединяет дополнительные изменения, которые вы подготовили.

Во-первых, вам нужно поэтапно внести изменения:

git add .

А затем поправьте:

git commit --amend --no-edit

Флаг --no-edit заставит команду не изменять сообщение фиксации. Если вам нужно уточнить новые изменения в новом сообщении, оставьте этот флаг выключенным, и вам будет предложено ввести новое сообщение фиксации.

Под капотом команда amend делает новый коммит с дополнительными изменениями, а затем полностью заменяет исходный коммит в истории Git. Старый коммит по-прежнему доступен из git reflog (подробнее об этом ниже), но в будущем новый коммит будет единственным существующим. Когда вы отправляете на удаленное репо, нет никакого способа узнать, что коммит был изменен, это чисто локальное изменение.

Из-за этого вам не захочется изменять коммиты, которые уже были отправлены, так как вы столкнетесь со многими проблемами и вам придется принудительно отправлять их на удаленный сервер, что никому не нужно.

Изменение только сообщения Git Commit

Если вам не нужно вносить никаких изменений и вы просто хотите исправить опечатку, вы также можете запустить amend без каких-либо изменений:

git commit --amend -m "an updated commit message"

Отмена изменений из коммитов

Команда Git amend работает, только если вы строго добавляете изменения. Когда мы говорим «добавлено», мы имеем в виду не только новые строки кода; изменение строки кода также добавляет изменения. Удаление строки кода или всего файла также является добавленным изменением, даже если это удаление данных из проекта, когда это изменение применяется.

Однако есть также случаи, когда вы можете захотеть удалить изменения из коммитов. Например, скажем, вы запустили:

git add .
git commit

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

Решение состоит в том, чтобы выполнить сброс, удалив коммит и отправив изменения обратно. Существует несколько видов сброса, но все они включают в себя получение коммитов из истории Git и отправку их обратно либо в промежуточную среду, либо в локальный каталог, либо прямо в корзину.

В этом случае вам нужен программный сброс, который отправит все изменения обратно в промежуточную версию. Вы можете использовать следующее сокращение для возврата к коммиту за HEAD, в противном случае вам нужно будет получить ссылку из git reflog:

git reset --soft HEAD~

Затем вам нужно будет удалить файл, который вы не хотите зафиксировать. Способ сделать это на самом деле также сброс, в данном случае смешанный сброс для определенного файла:

git reset --mixed filename

Это работает, потому что сброс этого одного файла удалит изменения из промежуточного хранения, и он не будет зафиксирован, когда вы повторите коммит.

Вы также можете выполнить смешанный сброс всего репозитория и git добавить все файлы, кроме того, который вам не нужен. Это проще сделать, если вы используете Git-клиент с графическим интерфейсом.

Нужно отменить/удалить коммит? Использовать возврат

Откат фиксации — самый простой способ удаления изменений. По сути, он берет все изменения из целевого коммита и применяет противоположные им. Если вы создали файл, он будет удален. Если вы удалили строку кода, этот код добавляется обратно. Это одобренный Git способ «удалить» или «отменить» коммит, поскольку оригинал все еще хранится в истории git.

Чтобы использовать его, запустите git log, чтобы просмотреть коммиты:

git log

Скопируйте эталонный идентификатор, а затем отмените фиксацию:

git revert 62ff517cc7c358eaf0bffdebbbe1b38dea92ba0f

Если вы только что застряли в vim, нажмите Q и, возможно, запустите git config --global core.editor \nano\.

Используйте перебазирование для чего-то более сложного

Перебазирование — это, по сути, метод перемещения коммитов в вашем репозитории. Вместо слияния rebase переписывает историю git, чтобы переместить отдельные коммиты в новое место. Исходные коммиты остались висящими и удалены из официальной истории Git, хотя они все еще там в git reflog.

Мы не будем вдаваться в подробности здесь, но если вам интересно, как это работает, вы можете прочитать наше руководство по использованию git rebase.

Что делать, если вы хотите вернуться?

К счастью, Git записывает каждое изменение, даже когда вы нарушаете правила и переписываете историю.

Каждый раз, когда ваша подсказка по какой-либо причине обновляется, Git сохраняет состояние содержимого каталога перед обновлением в Reference Log или reflog. Вы можете просмотреть журнал с помощью git reflog:

git reflog

Многие из них будут фактическими коммитами, но они также включают в себя и другие изменения. Если вам нужно вернуться к какому-либо отдельному изменению, вы можете выполнить полный сброс:

git reset --hard fdb9db9

Это обеспечивает хорошую подстраховку, но вы должны быть предупреждены, что reflog отслеживает только изменения, которые были фактически зафиксированы, а не только подготовленные, и отслеживает только движения кончика ветки. Кроме того, reflog хранит записи только в течение 90 дней. После этого вы сможете вернуться только к фактическим коммитам.