Как удалить коммит git
Перейти к содержимому

Как удалить коммит git

  • автор:

17. Удаление коммитов из ветки

Revert из предыдущего раздела является мощной командой, которая позволяет отменить любые коммиты в репозиторий. Однако, и оригинальный и «отмененный» коммиты видны в истории ветки (при использовании команды git log ).

Часто мы делаем коммит, и сразу понимаем, что это была ошибка. Было бы неплохо иметь команду «возврата», которая позволила бы нам сделать вид, что неправильного коммита никогда и не было. Команда «возврата» даже предотвратила бы появление нежелательного коммита в истории git log .

01 Команда reset

Мы уже видели команду reset и использовали ее для согласования буферной зоны и выбранного коммита (мы использовали коммит HEAD в нашем предыдущем уроке).

При получении ссылки на коммит (т.е. хэш, ветка или имя тега), команда reset …

  1. Перепишет текущую ветку, чтобы она указывала на нужный коммит
  2. Опционально сбросит буферную зону для соответствия с указанным коммитом
  3. Опционально сбросит рабочий каталог для соответствия с указанным коммитом

02 Проверьте нашу историю

Давайте сделаем быструю проверку нашей истории коммитов.

Выполните:
Результат:

Мы видим, что два последних коммита в этой ветке — «Oops» и «Revert Oops». Давайте удалим их с помощью сброса.

03 Для начала отметьте эту ветку

Но прежде чем удалить коммиты, давайте отметим последний коммит тегом, чтобы потом можно было его найти.

Выполните:

04 Сброс коммитов к предшествующим коммиту Oops

Глядя на историю лога (см. выше), мы видим, что коммит с тегом «v1» является коммитом, предшествующим ошибочному коммиту. Давайте сбросим ветку до этой точки. Поскольку ветка имеет тег, мы можем использовать имя тега в команде сброса (если она не имеет тега, мы можем использовать хэш-значение).

Выполните:
Результат:

Наша ветка master теперь указывает на коммит v1, а коммитов Oops и Revert Oops в ветке уже нет. Параметр —hard указывает, что рабочий каталог должен быть обновлен в соответствии с новым head ветки.

05 Ничего никогда не теряется

Что же случается с ошибочными коммитами? Оказывается, что коммиты все еще находятся в репозитории. На самом деле, мы все еще можем на них ссылаться. Помните, в начале этого урока мы создали для отмененного коммита тег «oops». Давайте посмотрим на все коммиты.

Выполните:
Результат:

Мы видим, что ошибочные коммиты не исчезли. Они все еще находятся в репозитории. Просто они отсутствуют в ветке master . Если бы мы не отметили их тегами, они по-прежнему находились бы в репозитории, но не было бы никакой возможности ссылаться на них, кроме как при помощи их хэш имен. Коммиты, на которые нет ссылок, остаются в репозитории до тех пор, пока не будет запущен сборщик мусора.

06 Опасность сброса

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

Однако, если ветка «расшарена» на удаленных репозиториях, сброс может сбить с толку других пользователей ветки.

Удалить коммиты из ветки Git

В этом посте мы обсудим, как удалить коммиты из ветки Git.

1. git сброс

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

Вы можете ссылаться на фиксацию через ее родословную, используя ее полный хэш SHA-1 или предоставляя частичный хеш, который должен быть не менее 4 символов и быть однозначным.

Если эти коммиты присутствуют в удаленном репозитории, вам нужно будет принудительно выполнить полный сброс в удаленный репозиторий.

Вот живой пример:

git reset --hard

Обратите внимание, что любые изменения, сделанные в рабочем каталоге с момента последней фиксации, автоматически отбрасываются. Чтобы избежать этого, сначала спрячьте свои локальные изменения, вызвав метод git-stash команда, которая, в свою очередь, также возвращает рабочий каталог в HEAD редакцию после сохранения ваших локальных изменений. git reset —hard HEAD часто используется для удаления всех незафиксированных изменений в соответствии с самой последней фиксацией в рабочем каталоге.

Если вы хотите сохранить свою работу и только отменить фиксацию, вы можете использовать —soft вариант.

Это показано ниже:

git reset soft

2. git вернуться

Не рекомендуется выполнять принудительную отправку в общедоступный или общий репозиторий; сделать git-revert вместо. Он создает новую фиксацию, которая отменяет все указанные изменения фиксации, а затем применяет ее к текущей ветке.

# Revert the commit 87859b5
git revert 87859b5

# Push to the remote
git push

Вот живой пример:

git revert

3. Интерактивный ребейзинг

Другой вероятный способ удаления комментариев — использование git-rebase команда.

Выполнение вышеуказанной команды откроет редактор со всеми фиксациями в вашей текущей ветке, которые идут после указанной фиксации. Чтобы удалить фиксацию, просто замените команду ‘выбрать’ на ‘удалить’ и закройте редактор. Вы также можете удалить соответствующую строку.

git rebase

Следующая команда удалит всю фиксацию e78d8b1 за один раз с помощью —rebase-merges режим с —onto вариант.

rebase drop specific commit

Это все об удалении коммитов из ветки Git.

Оценить этот пост

Средний рейтинг 4.96 /5. Подсчет голосов: 23

Голосов пока нет! Будьте первым, кто оценит этот пост.

Сожалеем, что этот пост не оказался для вас полезным!

Расскажите, как мы можем улучшить этот пост?

Спасибо за чтение.

Пожалуйста, используйте наш онлайн-компилятор размещать код в комментариях, используя C, C++, Java, Python, JavaScript, C#, PHP и многие другие популярные языки программирования.

Как мы? Порекомендуйте нас своим друзьям и помогите нам расти. Удачного кодирования ��

Git Remove Last Commit – How to Undo a Commit in Git

Dionysia Lemonaki

Dionysia Lemonaki

Git Remove Last Commit – How to Undo a Commit in Git

Git is a powerful tool and the most popular version control system. It is how developers and technical teams collaborate and work together on projects.

But what happens when you accidentally commit a file and realize that you shouldn’t have done that because that file contains an error?

There is no need to fret because Git allows you to undo your mistakes and go back to an earlier version of your project.

One of the most helpful features of Git is the ability to undo the changes you make to a project over time.

In this article, you will learn how to undo changes in Git depending on the state of your Git repository.

Here is what we will cover:

How to Undo Local Unstaged Changes in Git

Say you are working on your local machine. You made and saved some changes to a file locally, but you would like to discard them.

When you have yet to stage those changes, you haven’t used the git add command.

In this case, you need to use the git restore command.

Specifically, the git restore command will look something like this:

So, say you have a README.md file and you accidentally wrote and saved some text you want to discard.

You can first use the git status command to view the state of your Git repository.

This command will confirm that the file is unstaged (meaning you haven’t used git add yet), and will let you view the files you may want to undo:

Here is how you would undo the changes in the README.md file:

You can then use git status again to check the state of the repository:

Now, you have successfully discarded your most recent changes and reverted to the last committed version of your project.

How to Undo Local Staged Changes in Git

A file is staged when you have used the git add command.

So, say you made some changes to the README.md file locally, you used the git add command which staged the changes, and then you realized that the text contains some mistakes.

First, run git status to make sure you have staged the file (meaning you used git add ) :

As you can tell by the output of git status , you can use the following command to undo your changes:

This command will unstage the staged file, but will keep your changes.

Let’s run git status again:

Now, to discard the changes you made and restore the file to its original contents, use:

And let’s run git status one last time:

Now, the changes you made have gone and the file is reverted to the current committed version.

How to Undo Local Committed Changes in Git

Say you made changes to a file, you staged the file with the git add command, and you committed the file with the git commit command.

This means that the commit exists only locally and has not been pushed to a remote repository yet.

First, use git status to check that you committed the file:

Next, if you want to undo your last local commit, use the git log command:

The latest commit will have a commit hash (a long series of numbers and characters) and a (HEAD -> main) at the end – this is the commit you are looking to undo.

The second to last commit has a commit hash and a (origin/main) at the end – this is the commit you want to keep and the commit you pushed to the remote repository.

After that, use the following command to undo the commit:

Now, let’s use git log again.

You should see the commit hash, and a (HEAD -> main, origin/main) at the end.

The last commit you made is no longer part of the repository’s history and has been removed.

The command above restored everything to the version of the file prior to that accidental or mistaken commit and has gone back one commit.

Let’s check git status again

Keep in mind that although the git reset —soft HEAD

command undid your latest commit, it kept the changes you made.

How to Undo Public Committed Changes in Git

What if you made changes to a file, you staged the file git add , committed it with git command , and pushed it to a remote repository with git push – but then realized you shouldn’t have committed that file in the first place?

What do you do then?

First, use git status to check the state of the git repository:

In the section above, you saw that each commit has a commit hash, which is a long series of numbers and characters.

To see the short version of the commit hash, use the following command:

With the git log command, you can also check which commit you want to undo.

Say that your latest commit has a commit hash of cc3bbf7 , which is followed by (HEAD -> main, origin/main) , and a commit message such as «commit README.md file» .

To undo that specific commit, use the following command:

The command above will undo the changes by creating a new commit and reverting that file to its previous state, as if it never changed.

7.6 Инструменты Git — Перезапись истории

Неоднократно при работе с Git, вам может потребоваться по какой-то причине внести исправления в историю коммитов. Одно из преимуществ Git заключается в том, что он позволяет вам отложить принятие решений на самый последний момент. Область индексирования позволяет вам решить, какие файлы попадут в коммит непосредственно перед его выполнением; благодаря команде git stash вы можете решить, что не хотите продолжать работу над какими-то изменениями; также можете внести изменения в сделанные коммиты так, чтобы они выглядели как будто они произошли по-другому. В частности, можно изменить порядок коммитов, сообщения или изменённые в коммитах файлы, объединить вместе или разбить на части, полностью удалить коммит — но только до того, как вы поделитесь своими наработками с другими.

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

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

Изменение последнего коммита

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

Если вы хотите изменить только сообщение вашего последнего коммита, это очень просто:

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

Если вы создали коммит и затем хотите изменить зафиксированный снимок, добавив или изменив файлы (возможно, вы забыли добавить вновь созданный файл, когда совершали изначальный коммит), то процесс выглядит в основном так же. Вы добавляете в индекс необходимые изменения, редактируя файл и выполняя для него git add или git rm для отслеживаемого файла, а последующая команда git commit —amend берет вашу текущую область подготовленных изменений и делает её снимок для нового коммита.

Вы должны быть осторожными, используя этот приём, так как при этом изменяется SHA-1 коммита. Поэтому, как и с операцией rebase — не изменяйте ваш последний коммит, если вы уже отправили его в общий репозиторий.

При изменении коммита существует возможность изменить как его содержимое, так и сообщение коммита. Если в коммит внесены существенные изменения, то почти наверняка следует обновить и его сообщение, чтобы оно более точно отражало содержимое коммита.

С другой стороны, если изменения незначительны (исправление опечаток, добавление в коммит забытого файла), то текущее сообщение вполне можно оставить; чтобы лишний раз не вызывать редактор, просто добавьте измененные файлы в индекс и выполните команду:

Изменение сообщений нескольких коммитов

Для изменения коммита, расположенного раньше в вашей истории, вам нужно обратиться к более сложным инструментам. В Git отсутствуют инструменты для переписывания истории, но вы можете использовать команду rebase , чтобы перебазировать группу коммитов туда же на HEAD, где они были изначально, вместо перемещения их в другое место. С помощью интерактивного режима команды rebase , вы можете останавливаться после каждого нужного вам коммита и изменять сообщения, добавлять файлы или делать что-то другое, что вам нужно. Вы можете запустить rebase в интерактивном режиме, добавив опцию -i к git rebase . Вы должны указать, какие коммиты вы хотите изменить, передав команде коммит, на который нужно выполнить перебазирование.

Например, если вы хотите изменить сообщения последних трёх коммитов, или сообщение какого-то одного коммита этой группы, то передайте как аргумент команде git rebase -i родителя последнего коммита, который вы хотите изменить — HEAD

3 . Может быть, проще будет запомнить

3 , так как вы хотите изменить последние три коммита; но не забывайте, что вы, в действительности, указываете четвертый коммит с конца — родителя последнего коммита, который вы хотите изменить:

Напомним, что это команда перебазирования — каждый коммит, входящий в диапазон HEAD

3..HEAD , будет изменён вне зависимости от того, изменили вы сообщение или нет. Не включайте в такой диапазон коммит, который уже был отправлен на центральный сервер: сделав это, вы можете запутать других разработчиков, предоставив вторую версию одних и тех же изменений.

Выполнение этой команды отобразит в вашем текстовом редакторе список коммитов, в нашем случае, например, следующее:

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

Обратите внимание на обратный порядок. Команда rebase в интерактивном режиме предоставит вам скрипт, который она будет выполнять. Она начнет с коммита, который вы указали в командной строке ( HEAD

3 ) и повторит изменения, внесённые каждым из коммитов, сверху вниз. Наверху отображается самый старый коммит, а не самый новый, потому что он будет повторен первым.

Вам необходимо изменить скрипт так, чтобы он остановился на коммите, который вы хотите изменить. Для этого измените слово pick на слово edit напротив каждого из коммитов, после которых скрипт должен остановиться. Например, для изменения сообщения только третьего коммита, измените файл следующим образом:

Когда вы сохраните сообщение и выйдете из редактора, Git переместит вас к самому раннему коммиту из списка и вернёт вас в командную строку со следующим сообщением:

Эти инструкции говорят вам в точности то, что нужно сделать. Выполните:

Измените сообщение коммита и выйдите из редактора. Затем выполните:

Эта команда автоматически применит два оставшиеся коммита и завершится. Если вы измените pick на edit в других строках, то можете повторить эти шаги для соответствующих коммитов. Каждый раз Git будет останавливаться, позволяя вам исправить коммит, и продолжит, когда вы закончите.

Упорядочивание коммитов

Вы также можете использовать интерактивное перебазирование для изменения порядка или полного удаления коммитов. Если вы хотите удалить коммит «Add cat-file» и изменить порядок, в котором были внесены два оставшихся, то вы можете изменить скрипт перебазирования с такого:

Когда вы сохраните скрипт и выйдете из редактора, Git переместит вашу ветку на родителя этих коммитов, применит 310154e , затем f7f3f6d и после этого остановится. Вы, фактически, изменили порядок этих коммитов и полностью удалили коммит «Add cat-file».

Объединение коммитов

С помощью интерактивного режима команды rebase также можно объединить несколько коммитов в один. Git добавляет полезные инструкции в сообщение скрипта перебазирования:

Если вместо «pick» или «edit» вы укажете «squash», Git применит изменения из текущего и предыдущего коммитов и предложит вам объединить их сообщения. Таким образом, если вы хотите из этих трёх коммитов сделать один, вы должны изменить скрипт следующим образом:

Когда вы сохраните скрипт и выйдете из редактора, Git применит изменения всех трёх коммитов и затем вернёт вас обратно в редактор, чтобы вы могли объединить сообщения коммитов:

После сохранения сообщения, вы получите один коммит, содержащий изменения всех трёх коммитов, существовавших ранее.

Разбиение коммита

Разбиение коммита отменяет его и позволяет затем по частям индексировать и фиксировать изменения, создавая таким образом столько коммитов, сколько вам нужно. Например, предположим, что вы хотите разбить средний коммит на два. Вместо одного коммита «Update README formatting and add blame» вы хотите получить два разных: первый — «Update README formatting», и второй — «Add blame». Вы можете добиться этого, изменив в скрипте rebase -i инструкцию для разбиваемого коммита на «edit»:

Затем, когда скрипт вернёт вас в командную строку, вам нужно будет отменить индексацию изменений этого коммита, и создать несколько коммитов на основе этих изменений. Когда вы сохраните скрипт и выйдете из редактора, Git переместится на родителя первого коммита в вашем списке, применит первый коммит ( f7f3f6d ), применит второй ( 310154e ), и вернёт вас в консоль. Здесь вы можете отменить коммит с помощью команды git reset HEAD^ , которая, фактически, отменит этот коммит и удалит из индекса изменённые файлы. Теперь вы можете добавлять в индекс и фиксировать файлы, пока не создадите требуемые коммиты, а после этого выполнить команду git rebase —continue :

Git применит последний коммит ( a5f4a0d ) из скрипта, и ваша история примет следующий вид:

И снова, при этом изменились SHA-1 хеши всех коммитов в вашем списке, поэтому убедитесь, что ни один коммит из этого списка ранее не был отправлен в общий репозиторий. Обратите внимание, что последний коммит в списке ( f7f3f6d ) не изменился. Несмотря на то, что коммит был в списке перебазирования, он был отмечен как «pick» и применён до применения перебазирования, поэтому Git оставил его нетронутым.

Удаление коммита

Если вы хотите избавиться от какого-либо коммита, то удалить его можно во время интерактивного перебазирования rebase -i . Напишите слово «drop» перед коммитом, который хотите удалить, или просто удалите его из списка:

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

Если во время подобного перебазирования вы поняли, что это была не очень хорошая идея, то всегда можно остановиться. Просто выполните команду git rebase —abort и ваш репозиторий вернётся в то состояние, в котором он был до начала перебазирования.

Если вы завершили перебазирование, а затем решили, что полученный результат это не то, что вам нужно — воспользуйтесь командой git reflog , чтобы восстановить предыдущую версию вашей ветки. Дополнительную информацию по команде reflog можно найти в разделе Восстановление данных главы 10.

Дрю Дево создал практическое руководство с упражнениями по использованию git rebase . Найти его можно здесь: https://git-rebase.io/

Продвинутый инструмент: filter-branch

Существует ещё один способ переписывания истории, который вы можете использовать при необходимости изменить большое количество коммитов каким-то программируемым способом — например, изменить глобально ваш адрес электронной почты или удалить файл из всех коммитов. Для этого существует команда filter-branch , и она может изменять большие периоды вашей истории, поэтому вы, возможно, не должны её использовать кроме тех случаев, когда ваш проект ещё не стал публичным и другие люди ещё не имеют наработок, основанных на коммитах, которые вы собираетесь изменить. Однако, эта команда может быть очень полезной. Далее вы ознакомитесь с несколькими обычными вариантами использованиями этой команды, таким образом, вы сможете получить представление о том, на что она способна.

Команда git filter-branch таит в себе много подводных камней и более не является рекомендуемым способом изменения истории. Вместо этого, рассмотрите возможность использования Python скрипта git-filter-repo , который лучше подходит для большинства ситуаций, в которых вы обычно используете filter-branch . С документаций и исходным кодом скрипта можно ознакомиться здесь: https://github.com/newren/git-filter-repo.

Удаление файла из каждого коммита

Такое случается довольно часто. Кто-нибудь случайно зафиксировал огромный бинарный файл, неосмотрительно выполнив git add . , и вы хотите отовсюду его удалить. Возможно, вы случайно зафиксировали файл, содержащий пароль, а теперь хотите сделать ваш проект общедоступным. В общем, утилиту filter-branch вы, вероятно, захотите использовать, чтобы привести к нужному виду всю вашу историю. Для удаления файла passwords.txt из всей вашей истории вы можете использовать опцию —tree-filter команды filter-branch :

Опция —tree-filter выполняет указанную команду после переключения на каждый коммит и затем повторно фиксирует результаты. В данном примере, вы удаляете файл passwords.txt из каждого снимка вне зависимости от того, существует он или нет. Если вы хотите удалить все случайно зафиксированные резервные копии файлов, созданные текстовым редактором, то вы можете выполнить нечто подобное git filter-branch —tree-filter ‘rm -f *

Вы можете посмотреть, как Git изменит деревья и коммиты, а затем уже переместить указатель ветки. Как правило, хорошим подходом будет выполнение всех этих действий в тестовой ветке и, после проверки полученных результатов, установка на неё указателя основной ветки. Для выполнения filter-branch на всех ваших ветках, вы можете передать команде опцию —all .

Установка подкаталога как корневого каталога проекта

Предположим, вы выполнили импорт из другой системы контроля версий и получили в результате подкаталоги, которые не имеют никакого смысла ( trunk , tags и так далее). Если вы хотите сделать подкаталог trunk корневым для каждого коммита, команда filter-branch может помочь вам в этом:

Теперь вашим новым корневым каталогом проекта будет являться подкаталог trunk . Git также автоматически удалит коммиты, которые не затрагивали этот подкаталог.

Глобальное изменение адреса электронной почты

Ещё один типичный случай возникает, когда вы забыли выполнить git config для настройки своего имени и адреса электронной почты перед началом работы, или, возможно, хотите открыть исходные коды вашего рабочего проекта и изменить везде адрес вашей рабочей электронной почты на персональный. В любом случае вы можете изменить адрес электронный почты сразу в нескольких коммитах с помощью команды filter-branch . Вы должны быть осторожны, чтобы изменить только свои адреса электронной почты, для этого используйте опцию —commit-filter :

Эта команда пройдёт по всем коммитам и установит в них ваш новый адрес. Так как коммиты содержат значения SHA-1-хешей их родителей, эта команда изменяет хеш SHA-1 каждого коммита в вашей истории, а не только тех, которые соответствовали адресам электронной почты.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *