Перейти к содержимому

Как удалить все коммиты git

  • автор:

Как обнулить историю Git?

Ситуация такая: на сервере удалил репозиторий и создал заново, с локального теперь нужно сделать push , но если сделаю, то всю историю коммитов запишет на сервер. Как начать с нуля?

Отслеживать
34k 25 25 золотых знаков 130 130 серебряных знаков 222 222 бронзовых знака
задан 17 июн 2013 в 13:33
2,711 15 15 золотых знаков 54 54 серебряных знака 87 87 бронзовых знаков

скорее всего просто удалить папку .git , но не факт, я просто подумал что это можно сделать консольными git — командами.

17 июн 2013 в 13:35

я думаю, что удаление .git — самое правильное решение (копию перед этим лучше сделать). Но можно пойти хитрее — слить все коммиты в один:)

17 июн 2013 в 13:50
@KoVadim написал детальные инструкции по вашему предложению.
1 июл 2015 в 19:45

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

Все эти инструкции верны, если на удаленном сервере у вас пусто, а локально — есть проект и репозиторий Git с историей, которую вы хотите удалить.

Что будет потеряно безвозвратно

  1. Собственно, история. Вы точно хотите ее потерять? Ради нее весь Git и придумывался.
  2. Весь код в не-слитых (unmerged) ветках.
  3. Весь код в orphaned ветках.
  4. Метки (tags)

Быстрый способ

Найдите первый коммит в ветке, запомните его sha1.

 git log --oneline 

Переключитесь на тот коммит, который хотите сохранить в итоге.

git checkout master 

Теперь используем git reset —soft чтобы сделать из всей истории один коммит (подробнее — пункт 4.1: Как вернуться (откатиться) к более раннему коммиту? ).

git reset --soft git commit -m'слил историю в один коммит' 

Долгий способ

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

mkdir ../git-backup mv .git ../git-backup/.git 

Если не переместили локально, а забэкапили куда-то еще: удаляем папку.

rm -Rf .git 

Теперь заново инициализируем репозиторий:

git init 
git add . git commit -m'начал с нуля' 

Когда все готово

Подключаем удаленный репозиторий и заливаем на него изменения:

git remote add origin git push -u origin --all 

Отмена коммитов — Введение в Git

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

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

  • Забыли добавить в коммит нужные файлы
  • Изменения нужно «откатить», чтобы доработать
  • Изменения больше не актуальны, и их нужно удалить
  • Изменения были сделаны по ошибке, и их нужно отменить

По большей части Git движется «только вперед». Правильный подход при работе с ним — это создавать новое, а не изменять старое.

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

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

Git revert

Самая простая ситуация — отмена изменений. Фактически она сводится к созданию еще одного коммита, который выполняет изменения, противоположные тому коммиту, который отменяется:

Руками создавать подобный коммит довольно сложно, поэтому в Git добавили команду, автоматизирующую откат. Эта команда называется git revert :

# Этой команде нужен идентификатор коммита # Это коммит, которым мы удалили файл PEOPLE.md git revert aa600a43cb164408e4ad87d216bc679d097f1a6c # После этой команды откроется редактор, ожидающий ввода описания коммита # Обычно сообщение revert не меняют, поэтому достаточно просто закрыть редактор [main 65a8ef7] Revert "remove PEOPLE.md" 1 file changed, 1 insertion(+) create mode 100644 PEOPLE.md # В проект вернулся файл PEOPLE.md git log -p commit 65a8ef7fd56c7356dcee35c2d05b4400f4467ca8 Author: tirion Date: Sat Sep 26 15:32:46 2020 -0400 Revert "remove PEOPLE.md" This reverts commit aa600a43cb164408e4ad87d216bc679d097f1a6c. diff --git a/PEOPLE.md b/PEOPLE.md new file mode 100644 index 0000000..4b34ba8 --- /dev/null +++ b/PEOPLE.md @@ -0,0 +1 @@ +Haskell Curry 

Команда revert может отменять не только последний коммит, но и любой другой коммит из истории проекта. Согласитесь, это очень круто. Без системы контроля версий о таком нельзя было и мечтать.

Команда git reset

Представьте, что вам нужно удалить только что сделанный по ошибке коммит. Конечно, и в этом случае подходит git revert , но так история становится менее читаемой. Если этот коммит сделан был только сейчас и еще не отправлялся на GitHub, то лучше сделать так, как будто бы этого коммита не существовало в принципе.

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

Если коммит был отправлен во внешний репозиторий, например, на GitHub, то менять историю ни в коем случае нельзя. Это сломает работу у тех, кто работает с вами над проектом.

Для удаления коммита используется команда git reset :

# Добавляем новый коммит, который мы сразу же удалим echo 'test' >> INFO.md git add INFO.md git commit -m 'update INFO.md' [main 17a77cb] update INFO.md 1 file changed, 1 insertion(+) # Важно, что мы не делаем git push git reset --hard HEAD~ HEAD is now at 65a8ef7 Revert "remove PEOPLE.md" # Если посмотреть `git log`, то последнего коммита там больше нет 

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

Флаг —hard означает полное удаление. Без него git reset отменит коммит, но не удалит его, а поместит все изменения этого коммита в рабочую директорию, так что с ними можно будет продолжить работать.

Флаг HEAD~ означает «один коммит от последнего коммита». Если бы мы хотели удалить два последних коммита, то могли бы написать HEAD~2 :

HEAD (переводится как «голова») — так обозначается последний сделанный коммит. Подробнее эту терминологию мы разберем в уроке, посвященном внутреннему устройству Git.

Если не указывать флаг —hard , то по умолчанию подразумевается флаг —mixed . В таком варианте git reset отправляет изменения последнего коммита в рабочую директорию. Затем их можно исправить или отменить и выполнить новый коммит:

echo 'no code no pain' > README.md git add README.md git commit -m 'update README.md' [main f85e3a6] update README.md 1 file changed, 1 insertion(+) # Теперь откатываем последний коммит git reset HEAD~ Unstaged changes after reset: M README.md git status On branch main Your branch is up to date with 'origin/main'. Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: README.md 

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

Самостоятельная работа
  1. Выполните все шаги из урока
  2. Измените добавленный текст на No code No pain
  3. Закоммитьте изменения с сообщением update README.md
  4. Залейте изменения на GitHub

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

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

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

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

01 Команда reset

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

Если выполнить команду reset с указанием ссылки на коммит (т.е. метки HEAD , имени ветки или тега, хеша коммита), то команда.

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

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

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

Выполните
git log 
Результат
$ git log 86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main) [Alexander Shvets] 6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets] b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets] 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets] 78433de 2023-11-28 | Added h1 tag [Alexander Shvets] 5836970 2023-11-28 | Initial commit [Alexander Shvets] 

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

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

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

Выполните
git tag oops 
Результат
$ git log 86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main, tag: oops) [Alexander Shvets] 6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets] b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets] 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets] 78433de 2023-11-28 | Added h1 tag [Alexander Shvets] 5836970 2023-11-28 | Initial commit [Alexander Shvets] 

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

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

Выполните
git reset --hard v1 git log 
Результат
$ git reset --hard v1 HEAD is now at b7614c1 Added HTML header $ git log b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets] 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets] 78433de 2023-11-28 | Added h1 tag [Alexander Shvets] 5836970 2023-11-28 | Initial commit [Alexander Shvets] 

Наша ветка main теперь указывает на коммит v1 , а коммитов «Revert Oops» и «Oops» в ветке уже нет. Параметр —hard указывает, что рабочая директория должна быть приведена к тому состоянию, которое соответствует HEAD -коммиту ветки.

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

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

Выполните
git log --all 
Результат
$ git log --all b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets] 86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (tag: oops) [Alexander Shvets] 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets] 6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets] 78433de 2023-11-28 | Added h1 tag [Alexander Shvets] 5836970 2023-11-28 | Initial commit [Alexander Shvets] 

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

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

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

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

Удаляем коммит с GitHub

Работая с системами контроля версий иногда возникает ситуация, когда по той или иной причине (чаще по той) нужно отменить последний коммит. Сделать это на локалке как 2 пальца. В соответствующей ветке в консоли пишем такую команду:

git reset --hard commit_id // commit_id - идентификатор коммита, к которому нужно вернуться.
Внимание!

Имейте ввиду, что опция —hard отвечает за полную потерю памяти изменений. Всё что было в коммите и всё что вы сделали после него будет удалено. Чтобы избежать этого, используйте опции —soft или —mixed . Подробнее читайте тут.

А что делать, если изменения опубликованы на GitHub? Всего лишь выполнить ещё одну команду:

$ git push --force

Владельцам же инструмента разработки phpStorm всё это можно сделать ещё проще. Достаточно лишь пары кликов. Клавиши пусть молодые жмут ))

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

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