Очень короткая заметка из серии «Хозяйке на заметку».

Предисловие


У плохо организованных разработчиков, типа меня, часто так бывает, что накомитишь всякого, а потом оказывается что не то и не туда, но git помнит всё и весь этот разгул анархии остаётся в истории.
Мне всегда казалось что это можно исправить, но сколько раз я не начинал искать ответа на этот вопрос — как в git удалить камиты — столько раз мне это не удавалось.
А всё потому что мои поиски приводили меня к rebase, а надо было искать reset.
На мой вкус вопрос недостаточно освещён и моя заметка призвана закрыть этот пробел.

Алгоритм


  1. git branch // смотрим где мы находимся — в какой ветке
  2. git status // проверяем что у нас актуальная версия
  3. git log // ищем камит к которому мы хотим откатиться
  4. sudo git reset --hard 7bcdf46b14b2dacc286b0ad469d5f9022d797f68 // указываем камит начиная с которого нам надо забыть наши изменения, при этом из локальной ветки все камиты с указанного будут забыты — удалены
  5. git push --force origin feature/draft // заливаем локальную ветку в оригинальную (ветку сервера) — из оригинальной ветки будут удалены все «лишние» камиты
  6. Победа !

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

PS
На самом деле камиты из репозитория не удаляются, удаляется связь этих камитов с деревом изменений, таким образом эти камиты пропадают из ветки, но git помнит всё.
Поделиться с друзьями
-->

Комментарии (34)


  1. DrPass
    12.06.2017 16:54
    +10

    Сначала неплохо было бы эти «камиты» поудалять из вашей заметки.


  1. evgeniy2194
    12.06.2017 17:01
    +10

    Очень полезная заметка.

    Хотелось бы увидеть заметку о том как дабавить новые камиты


    1. sl_bug
      12.06.2017 17:04
      +1

      Я вот так делаю новые камиты — git commit -am 'первый камит'


    1. SbWereWolf
      12.06.2017 17:04
      -4

      в документации к гиту легко найти как сделать ресет, но ни где в документации не сказано как после этого изменения в локальной ветке, накатить на удалённую ветку.

      польза заметки — не в том что она рассказывает что такое reset, а в том как в origin залить.

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


      1. sl_bug
        12.06.2017 17:06

        1. SbWereWolf
          12.06.2017 17:17
          -11

          я не к тому что этого в документации нет, я к тому что не озвучена комбинация reset + push,
          товарищам которые из командной строки общаются с git, проблема кажется надуманной,
          но есть и другие товарищи которые юзают git через GUI, в gui ( source tree) нет по отдельности push, SourceTree когда видит что у тебя локально камитов недостаёт, предлагает сделать pull и ни какой push --force не предлагается.

          но снобам откуда знать о проблемах gui git-клиентов, у них взбурлило, они минуса шлют :)) мой прошлый рекорд всего 12 минусов, тут думаю хотя бы 20 отхвачу, аудитория Хабра не прощает инакомыслия :)


          1. 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…


            1. SbWereWolf
              12.06.2017 17:40
              -1

              «git remove commits from remote branch» — до такого запроса надо дойти, я до него дошёл спустя два часа поисков.


              1. morikvendy
                12.06.2017 17:57
                +2

                А что же вы гуглили эти два часа? Разве указанный запрос это не ровно то, что вы хотели сделать?
                Как то странно выходит, у вас была задача удалить коммиты из удаленной ветки, но вы два часа искали что-то, не вводя в поисковик «удалить коммиты из удаленной ветки», кстати, даже если ввести это на русском, то вторая ссылка приведет на хабр, на статью аналогичную вашей


                1. SbWereWolf
                  12.06.2017 18:00

                  по старой памяти я гуглил rebase, конечно я два часа не только гуглил но и экспериментировал. не только доки гуглил, но больше примеры. и «задавал» вопросы гуглу с разными формулировками.

                  когда знаешь ответ на вопрос найти его не сложно :) я бы в другой ситуации.

                  не дал мне Гугл вашу ссылку на Хабр, если бы дал я бы свой пост не делал.


                  1. Borz
                    12.06.2017 20:40
                    +1

                    по старой памяти я гуглил rebase

                    вы искали в Googl использование команды rebase, а не озвучивали поисковику вашу проблему.
                    сравните: "git удалить коммиты из удалённой ветки" и "git как с помощью rebase удалить кометы из удалённой ветки".
                    Проблема преждевременной оптимизации запроса


                    1. nick_volynkin
                      13.06.2017 05:18
                      +2

                      На Stackoverflow это называют "XY problem". Вместо решения задачи человек ищет решение задачи непременно каким-то инструментом, который ему известен. Оно же: "забиваю гвозди, как правильно держать микроскоп".


                      1. Hithroc
                        13.06.2017 08:09
                        +1

                        Вообще XY problem пошел из IRC, насколько мне известно.
                        http://mywiki.wooledge.org/XyProblem


                        1. grossws
                          13.06.2017 12:45

                          Из usenet'а IIRC


          1. TyVik
            12.06.2017 20:00
            -1

            Тут не в инакомыслии дело. Просто то, что Вы предлагаете — недопустимо. От слова совсем. Нельзя делать push --force после rebase — таким образом можно порушить работу стороннего человека. При этой операции создаётся отдельная ветка, которая считается HEAD. Rebase можно применять очень осторожно и только локально. Пожалуйста, прочитайте Pro Git, это очень полезная и в то же время интересная книга.


            1. sl_bug
              12.06.2017 20:04

              Всегда делаю форс пуши в свои ветки. И именно после rebase — squash. Просто нельзя в одной ветке нескольким людям работать.


              1. voronElf
                13.06.2017 11:44

                А у вас тестировщики не пуллят код на тестовом серваке после форс пушей на фиксах багов?
                Зачем публиковать ветку в центральном репозитории, если ей никто кроме вас не пользуется?


  1. saggid
    12.06.2017 17:03
    +3

    Ну, можно ещё написать вот так:


    git reset --hard HEAD~5

    Что эквивалентно откату назад на 5 камитов) Очень удобно так делать) Кстати, лучше не выполнять эту команду через sudo — иначе от суперюзера появятся файлы в проекте, что может в итоге привести к проблемам с правами доступа при работе приложения.


    1. SbWereWolf
      12.06.2017 17:09
      -8

      без sudo почему то не работает, наверное потому что надо вносить изменения в файлы которые были сделаны из под супер юзера.


      1. alexyr
        12.06.2017 17:15
        +10

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


        1. nick_volynkin
          13.06.2017 05:22

          Хуже, когда автор статьи не осилил man.


      1. saggid
        12.06.2017 20:16
        +2

        Выполните волшебную команду :)


        sudo chown myusername ~ -R

        Она присвоит текущего пользователя всем файлам в вашей домашней директории линукса) И дальше уже можно спокойно всё делать без sudo.


        1. saggid
          12.06.2017 20:23
          +3

          Даже лучше вот так, чтобы точно текущего пользователя:


          sudo chown `whoami`:`whoami` ~ -R


  1. apro
    12.06.2017 17:18
    +2

    А всё потому что мои поиски приводили меня к rebase, а надо было искать reset.

    А почему собственно не rebase,
    делаешь git rebase -i HEAD~5 в появившемся редакторе удаляешь нужные
    строчки, сохраняешь и выходишь из редактора. Намного же проще чем несколько команд?


  1. demfloro
    12.06.2017 18:45
    +3

    Думаю лучше порекомендовать бесплатную книгу Pro Git, доступна на английском и на русском.


  1. Alex_ME
    12.06.2017 19:06
    +3

    Мне кажется, что это способ отстрелить себе ноги, если удаленную ветку кто-то до этого себе скачал.


  1. AlexLeonov
    12.06.2017 21:05
    +6

    Я бы посоветовал удалить вам эту статью. Всё равно она будет набирать только минусы. А кому-то начинающему может стать сборником вредных советов, если он случайно придёт на эту статью из поисковика.


    1. SbWereWolf
      13.06.2017 11:51
      -1

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

      и если кому то хочется свою ненависть выразить в минусе — сколько угодно. Собака лает, караван идёт.


  1. WildZero
    12.06.2017 22:53
    +6

    Надо на хабре добавить функцию скрытия опасных статей. Чувствую завтра будет много запоротых репозиториев от подобных «заметок хозяйке»


  1. Finesse
    13.06.2017 04:34

    Это не уровень Хабра. Такие заметки лучше постить на Stack Overflow в формате «сам спросил, сам ответил».


    1. nick_volynkin
      13.06.2017 05:29

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


      Имхо, лучше вообще не постить такие заметки, а вместо этого внимательно читать маны, Хабр и StackOverflow.


      1. Finesse
        13.06.2017 05:35
        +1

        Именно поэтому и надо постить на StackOverflow, потому что ответ автора заминусуют, он уйдёт вниз, а правильный ответ попадёт наверх. В итоге, случайный посетитель из Google увидит правильный ответ.


  1. 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 – далеко не везде используется и правильно настроена защита стабильных веток.
    • Выполнять операции с репозиторием под рутом нельзя, потому что после этого в нем появляются принадлежащие руту файлы (как починить).


  1. Eldhenn
    13.06.2017 11:52

    I like to come it, come it!