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


Автор материала, перевод которого мы публикуем сегодня, собирается обсудить распространённые ошибки, которые совершают программисты при работе с Git, и поговорить о том, как с этими ошибками бороться.

Ошибка в сообщении последнего коммита


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

git commit --amend

Эта команда откроет редактор и позволит внести изменения в последнее сообщение коммита. Никому кроме вас не стоит знать, что вы написали «Initial commment» с тремя «m».

Ошибка в имени ветки


Предположим, что на часах почти 15:00, а вы ещё не обедали. В результате, терзаемые голодом, вы назвали новую ветку feature-brunch. Вкуснятина, ничего не скажешь.

Эту проблему тоже можно решить. Переименовать ветку можно так же, как переименовывают файлы с помощью команды mv. Речь идёт о перемещении её в новое место с правильным именем:

git branch -m feature-brunch feature-branch

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

git push origin --delete feature-brunch
git push origin feature-branch

Случайный коммит изменений в ветку master


Предположим, вы работаете над некоей новой возможностью, и, в спешке, забыли создать для неё новую ветку. Вы закоммитили уже кучу файлов и всё это лежит в ветке master. Переместить все эти изменения в новую ветку можно с помощью следующих трёх команд. Обратите внимание на то, что если вы не воспользовались, в применении к изменениям, командами commit или stash, они будут утеряны.

git branch feature-branch
git reset HEAD~ --hard
git checkout feature-branch

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

Работа с файлами, которые забыли добавить в последний коммит


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

git add missed-file.txt
git commit --amend

После этого вы можете изменить сообщение коммита, либо оставить его таким же, каким оно было.

Добавление не того файла в репозиторий


Как быть, если ваша ошибка представляет собой полную противоположность предыдущей? Что если вы добавили в индекс файл, который не собираетесь коммитить? Это может быть какой-нибудь ENV-файл, директория сборки проекта, фото вашей собаки, которое вы случайно сохранили не в той папке. Всё это можно исправить.

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

git reset /assets/img/misty-and-pepper.jpg

Если вы продвинулись достаточно далеко и успели изменение закоммитить, то знайте, что и это поправимо. Придётся лишь воспользоваться ещё несколькими командами:

git reset --soft HEAD~1
git reset /assets/img/misty-and-pepper.jpg
rm /assets/img/misty-and-pepper.jpg
git commit

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

Что делать, если всё пошло не так?


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

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

git reflog

Git помнит все наши действия и в результате выполнения этой команд можно увидеть примерно следующее:

3ff8691 (HEAD -> feature-branch) HEAD@{0}: Branch: renamed refs/heads/feature-brunch to refs/heads/feature-branch
3ff8691 (HEAD -> feature-branch) HEAD@{2}: checkout: moving from master to feature-brunch
2b7e508 (master) HEAD@{3}: reset: moving to HEAD~
3ff8691 (HEAD -> feature-branch) HEAD@{4}: commit: Adds the client logo
2b7e508 (master) HEAD@{5}: reset: moving to HEAD~1
37a632d HEAD@{6}: commit: Adds the client logo to the project
2b7e508 (master) HEAD@{7}: reset: moving to HEAD
2b7e508 (master) HEAD@{8}: commit (amend): Added contributing info to the site
dfa27a2 HEAD@{9}: reset: moving to HEAD
dfa27a2 HEAD@{10}: commit (amend): Added contributing info to the site
700d0b5 HEAD@{11}: commit: Addded contributing info to the site
efba795 HEAD@{12}: commit (initial): Initial commit

Обратите внимание на самую левую колонку этого списка. Тут содержатся индексы. Если вам нужно вернуться назад, в некий момент прошлого, выполните следующую команду, заменив {index} соответствующей ссылкой, например — dfa27a2. Выглядит эта команда так:

git reset HEAD@{index}

Итоги


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

Уважаемые читатели! Знаете о каких-нибудь интересных приёмах работы с Git? Если так — просим ими поделиться.

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


  1. Doomsday_nxt
    12.09.2018 12:59

    1. Ayahuaska
      12.09.2018 16:52
      +1

      Жду статью про `Как добавить изменения в репозиторий`.


    1. arturpanteleev
      12.09.2018 17:14

      Судя по числу плюсов, которое набрала данная статья, то «рерайт» этой информации можно каждый месяц(буквально, статья по ссылке от 10 августа) публиковать, а большинство будет радо


      1. ser-mk
        13.09.2018 00:44

        Плюсики возможно от сотрудников компании… вот вся прелесть корпоративного блога)


    1. ainoneko
      12.09.2018 18:14

      Там же ошибочная еда была другая: future-brunch, а не feature-brunch.


    1. c0f04
      12.09.2018 18:49
      +1

      На хабре не хватает кнопочки «Mark as duplicate». :)


      1. shurup
        13.09.2018 08:26

        Я уже писал в редакцию Хабры запрос на проверку дублей (хотя бы тупо по URL'у, а лучше бы, конечно, похитрее…) при создании новых переводов. И предлагаемая вот кнопочка тоже была бы полезна, т.к. в данном случае URL не совпадает (блогер на Medium не стал напрягаться хотя бы указанием оригинального автора и ссылки…).


    1. ru_vds Автор
      13.09.2018 09:40

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

      Обычно мы удаляем дубли, но за час ее успели добавить в избранное более 50 человек, сейчас уже более 240, поэтому мы посчитали, что все таки статья представляет интерес и решили ее не удалять.


      1. shurup
        13.09.2018 12:49

        По названию не нашли, а по смыслу не проверяете? Если уже были статьи про типичные ошибки в Git, я обязательно посмотрю на их содержание перед тем, как постить новую.


    1. Cheater
      13.09.2018 09:44
      +2

      Самое весёлое, что статья даёт вредные советы и переводчики понеслись распространять их дальше. Ни слова о том, что commit --amend переписывает историю и допустим только на локальной ветке, а за тем, кто переписывает историю публичной ветки, приезжает специальная расстрельная команда.


      1. gsmetal
        13.09.2018 12:10
        +1

        В нашем переводе в бонусе от переводчика об этом явно сказано.


  1. Nokse
    13.09.2018 09:33

    Зачем писать
    git reset HEAD@{index}
    если можно просто
    git reset {index}?


  1. balexa
    13.09.2018 10:09

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


  1. Mabusius
    13.09.2018 10:24

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


    1. balexa
      13.09.2018 13:05

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

      Вопрос равносилен «Может я не правильно работаю с электронной почтой, но зачем писать письмо, если не собираетесь отправлять его прямо сейчас».


    1. capslocky
      13.09.2018 13:08

      Я бы назвал такие причины:
      1. Прежде чем пушать новую порцию коммитов я их всех просмотраиваю, а также смотрю итоговый diff ветки «было-стало», и иногда вношу правки.
      2. Каждый пуш — это коннект и передача данных на сервер. Зачем мне делать 10 пушей, если я могу сделать 1 пуш в конце?
      3. Собственно я могу вообще не пушать ветку пока она никому не нужна или пока она не смерджена.
      4. Если на ветке работает кто-то еще, то не всегда допустимо просто пушнуть новый коммит. Не говоря уже о мердж-конлфиктах.
      5. У меня нет интернета (самое банальное).


      1. Mabusius
        13.09.2018 17:11

        del


  1. eCybernetics
    13.09.2018 23:31

    Помню, как узнал когда-то, про команду amend — моему щенячему восторгу не было предела. А, еще больше "восторга" у меня было, когда я сделал amend в запушений коммит.
    P.S. И, таки да — растрельная команда, во главе с тим-лидом, приехала и таки да — вставила)))


  1. Ilya81
    14.09.2018 21:33

    git branch feature-branch
    git reset HEAD~ --hard
    git checkout feature-branch

    Зачем так сложно? Можно проще и без риска потерять изменения, если stash не сработает (сам не всегда замечаю, что команда завершилась ошибкй):
    git checkout -b feature-branch
    git rev-parse master | xargs -L 1 git cherry-pick $0