Предисловие
У плохо организованных разработчиков, типа меня, часто так бывает, что накомитишь всякого, а потом оказывается что не то и не туда, но git помнит всё и весь этот разгул анархии остаётся в истории.
Мне всегда казалось что это можно исправить, но сколько раз я не начинал искать ответа на этот вопрос — как в git удалить камиты — столько раз мне это не удавалось.
А всё потому что мои поиски приводили меня к rebase, а надо было искать reset.
На мой вкус вопрос недостаточно освещён и моя заметка призвана закрыть этот пробел.
Алгоритм
- git branch // смотрим где мы находимся — в какой ветке
- git status // проверяем что у нас актуальная версия
- git log // ищем камит к которому мы хотим откатиться
- sudo git reset --hard 7bcdf46b14b2dacc286b0ad469d5f9022d797f68 // указываем камит начиная с которого нам надо забыть наши изменения, при этом из локальной ветки все камиты с указанного будут забыты — удалены
- git push --force origin feature/draft // заливаем локальную ветку в оригинальную (ветку сервера) — из оригинальной ветки будут удалены все «лишние» камиты
- Победа !
Если есть более правильный способ, то прошу озвучить в коментах.
PS
На самом деле камиты из репозитория не удаляются, удаляется связь этих камитов с деревом изменений, таким образом эти камиты пропадают из ветки, но git помнит всё.
Комментарии (34)
evgeniy2194
12.06.2017 17:01+10Очень полезная заметка.
Хотелось бы увидеть заметку о том как дабавить новые камитыSbWereWolf
12.06.2017 17:04-4в документации к гиту легко найти как сделать ресет, но ни где в документации не сказано как после этого изменения в локальной ветке, накатить на удалённую ветку.
польза заметки — не в том что она рассказывает что такое reset, а в том как в origin залить.
Если у вас не было такой проблемы, то я рад за вас.sl_bug
12.06.2017 17:06SbWereWolf
12.06.2017 17:17-11я не к тому что этого в документации нет, я к тому что не озвучена комбинация reset + push,
товарищам которые из командной строки общаются с git, проблема кажется надуманной,
но есть и другие товарищи которые юзают git через GUI, в gui ( source tree) нет по отдельности push, SourceTree когда видит что у тебя локально камитов недостаёт, предлагает сделать pull и ни какой push --force не предлагается.
но снобам откуда знать о проблемах gui git-клиентов, у них взбурлило, они минуса шлют :)) мой прошлый рекорд всего 12 минусов, тут думаю хотя бы 20 отхвачу, аудитория Хабра не прощает инакомыслия :)morikvendy
12.06.2017 17:39+1В gui конечно нет кнопок и на половину возможных действий гита и это нормально и правильно, специально для таких случаев есть кнопка «Терминал», которая открывает консоль из которой все это можно сделать.
Мне всегда казалось что это можно исправить, но сколько раз я не начинал искать ответа на этот вопрос — как в git удалить камиты — столько раз мне это не удавалось.
А всё потому что мои поиски приводили меня к rebase, а надо было искать reset.
Вводим в google волшебную фразу «git remove commits from remote branch» вторая ссылка ведет на stackoverflow, и там как раз говорят про сочетание reset + push --force. Более того в статье по первой ссылке тоже это описано в разделе «About History Rewriting» — case 1…SbWereWolf
12.06.2017 17:40-1«git remove commits from remote branch» — до такого запроса надо дойти, я до него дошёл спустя два часа поисков.
morikvendy
12.06.2017 17:57+2А что же вы гуглили эти два часа? Разве указанный запрос это не ровно то, что вы хотели сделать?
Как то странно выходит, у вас была задача удалить коммиты из удаленной ветки, но вы два часа искали что-то, не вводя в поисковик «удалить коммиты из удаленной ветки», кстати, даже если ввести это на русском, то вторая ссылка приведет на хабр, на статью аналогичную вашейSbWereWolf
12.06.2017 18:00по старой памяти я гуглил rebase, конечно я два часа не только гуглил но и экспериментировал. не только доки гуглил, но больше примеры. и «задавал» вопросы гуглу с разными формулировками.
когда знаешь ответ на вопрос найти его не сложно :) я бы в другой ситуации.
не дал мне Гугл вашу ссылку на Хабр, если бы дал я бы свой пост не делал.Borz
12.06.2017 20:40+1по старой памяти я гуглил rebase
вы искали в Googl использование команды rebase, а не озвучивали поисковику вашу проблему.
сравните: "git удалить коммиты из удалённой ветки" и "git как с помощью rebase удалить кометы из удалённой ветки".
Проблема преждевременной оптимизации запросаnick_volynkin
13.06.2017 05:18+2На Stackoverflow это называют "XY problem". Вместо решения задачи человек ищет решение задачи непременно каким-то инструментом, который ему известен. Оно же: "забиваю гвозди, как правильно держать микроскоп".
Hithroc
13.06.2017 08:09+1Вообще XY problem пошел из IRC, насколько мне известно.
http://mywiki.wooledge.org/XyProblem
TyVik
12.06.2017 20:00-1Тут не в инакомыслии дело. Просто то, что Вы предлагаете — недопустимо. От слова совсем. Нельзя делать push --force после rebase — таким образом можно порушить работу стороннего человека. При этой операции создаётся отдельная ветка, которая считается HEAD. Rebase можно применять очень осторожно и только локально. Пожалуйста, прочитайте Pro Git, это очень полезная и в то же время интересная книга.
sl_bug
12.06.2017 20:04Всегда делаю форс пуши в свои ветки. И именно после rebase — squash. Просто нельзя в одной ветке нескольким людям работать.
voronElf
13.06.2017 11:44А у вас тестировщики не пуллят код на тестовом серваке после форс пушей на фиксах багов?
Зачем публиковать ветку в центральном репозитории, если ей никто кроме вас не пользуется?
saggid
12.06.2017 17:03+3Ну, можно ещё написать вот так:
git reset --hard HEAD~5
Что эквивалентно откату назад на 5 камитов) Очень удобно так делать) Кстати, лучше не выполнять эту команду через sudo — иначе от суперюзера появятся файлы в проекте, что может в итоге привести к проблемам с правами доступа при работе приложения.
SbWereWolf
12.06.2017 17:09-8без sudo почему то не работает, наверное потому что надо вносить изменения в файлы которые были сделаны из под супер юзера.
alexyr
12.06.2017 17:15+10Исправить права под нужного юзера и больше не создавать файлы под рутом.
И вообще, статьи типа «тем, кто не осилил man» на хабре не очень любят
saggid
12.06.2017 20:16+2Выполните волшебную команду :)
sudo chown myusername ~ -R
Она присвоит текущего пользователя всем файлам в вашей домашней директории линукса) И дальше уже можно спокойно всё делать без sudo.
saggid
12.06.2017 20:23+3Даже лучше вот так, чтобы точно текущего пользователя:
sudo chown `whoami`:`whoami` ~ -R
apro
12.06.2017 17:18+2А всё потому что мои поиски приводили меня к rebase, а надо было искать reset.
А почему собственно не rebase,
делаешьgit rebase -i HEAD~5
в появившемся редакторе удаляешь нужные
строчки, сохраняешь и выходишь из редактора. Намного же проще чем несколько команд?
demfloro
12.06.2017 18:45+3Думаю лучше порекомендовать бесплатную книгу Pro Git, доступна на английском и на русском.
Alex_ME
12.06.2017 19:06+3Мне кажется, что это способ отстрелить себе ноги, если удаленную ветку кто-то до этого себе скачал.
AlexLeonov
12.06.2017 21:05+6Я бы посоветовал удалить вам эту статью. Всё равно она будет набирать только минусы. А кому-то начинающему может стать сборником вредных советов, если он случайно придёт на эту статью из поисковика.
SbWereWolf
13.06.2017 11:51-1для меня это полезная статья, если люди одно правило применяют ко всем ситуациям то это их проблемы, я выбираю способы в зависимости от условий, в моих условиях это правильное решение.
и если кому то хочется свою ненависть выразить в минусе — сколько угодно. Собака лает, караван идёт.
WildZero
12.06.2017 22:53+6Надо на хабре добавить функцию скрытия опасных статей. Чувствую завтра будет много запоротых репозиториев от подобных «заметок хозяйке»
Finesse
13.06.2017 04:34Это не уровень Хабра. Такие заметки лучше постить на Stack Overflow в формате «сам спросил, сам ответил».
nick_volynkin
13.06.2017 05:29На стеке вопрос бы закрыли как дубликат а ответ заминусовали точно так же, потому что он ошибочный и вообще деструктивный.
Имхо, лучше вообще не постить такие заметки, а вместо этого внимательно читать маны, Хабр и StackOverflow.
Finesse
13.06.2017 05:35+1Именно поэтому и надо постить на StackOverflow, потому что ответ автора заминусуют, он уйдёт вниз, а правильный ответ попадёт наверх. В итоге, случайный посетитель из Google увидит правильный ответ.
nick_volynkin
13.06.2017 05:51+4Попробую подвести итоги. В статье есть несколько существенных ошибок:
- Статья на самом деле решает задачу "как удалить коммиты из локальной ветки, а потом из ветки на удаленном репозитории", но из заголовка и текста этого не понять.
- Статья не обучает использованию команды
git reset
:
- Не рассказывает о других популярных вариантах использования:
reset
без параметров,reset --soft
. Да и проreset --hard
толком не рассказывает. - Поскольку
git reset --hard
переписывает историю, обязательно нужно было рассказать 0) как удалять коммиты, не теряя изменения 1) что переписывать историю можно только в своих фиче-ветках, 2) как восстанавливать коммиты с помощьюgit reflog
.
- Не рассказывает о других популярных вариантах использования:
- При любом упоминании
git push --force
нужно подробно рассказывать, куда нельзя и куда можно форс-пушить. Иначе кто-нибудь запушит вmaster
– далеко не везде используется и правильно настроена защита стабильных веток. - Выполнять операции с репозиторием под рутом нельзя, потому что после этого в нем появляются принадлежащие руту файлы (как починить).
DrPass
Сначала неплохо было бы эти «камиты» поудалять из вашей заметки.