image

Сегодня ни один проект не обходится без контроля версий с помощью Git под колпаком. Хорошее знание Git поможет вам улучшить свои навыки разработчика, ускорить рабочий процесс и действительно улучшить качество вашей кодовой базы. Однако для этого необходимо немного выйти за пределы привычной нам зоны комфорта. Оказывается, в Git есть нечто большее, чем просто commit, push и pull.

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

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

Оглавление:

1. Восстановление удалённых коммитов
2. Очистка истории коммитов
3. Использование субмодулей для управления сторонним кодом
4. Генерируем коммиты с точностью

Восстановление удалённых коммитов


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

imageЧто если вы хотите восстановить удалённый коммит? Вот тут-то вам и пригодится Reflog

Вот один из таких способов сделать это:

$ git reset --hard 2b504bee

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

Ваше сердце начинает колотиться, пот течёт ручьём — вы знаете, как это бывает.

Теперь возникает вопрос на миллион долларов: как вернуть эти, казалось бы, удалённые коммиты? К счастью, есть ответ: «Reflog».

Использование Reflog для восстановления потерянных стейтов


Вы можете считать Reflog «журналом» Git: это место, где Git протоколирует каждое движение указателя HEAD. Или другими словами: все наиболее интересные действия, такие как commit, merge, checkout, rebase, cherry-pick и другие. Это, конечно, делает его идеальным инструментом для тех неизбежных ситуаций, когда что-то идёт не так.

Давайте откроем Reflog для нашего примера и посмотрим, как он сможет нам помочь:

$ git reflog

imageReflog в действии, с полным журналом всех коммитов, до и после ошибки

Первое и самое важное, что нужно знать о Reflog, это то, что он упорядочен в хронологическом порядке. И действительно: с самым верхним (другими словами, самым новым) элементом мы явно накосячили, когда поспешно использовали git reset и потеряли несколько наших коммитов.

Решение для устранения нашей проблемы довольно простое: мы можем просто вернуться к состоянию до ошибки. И это состояние чётко фиксируется в Reflog, прямо под нашей фатальной командой reset. Чтобы отменить нашу ошибку, мы можем просто использовать git reset ещё раз, чтобы восстановить этот, казалось бы, потерянный стейт:

$ git reset e5b19e4

Вы также можете добиться того же результата несколько быстрее. Как группа дружелюбных и увлечённых разработчиков графического интерфейса Git «Tower», мы стремимся решить общие болевые точки, связанные с Git. Поэтому в нашем маленьком инструменте вы можете достичь тех же результатов, просто нажав [CMD] + [Z] — как если бы вы хотели исправить простую опечатку в вашем текстовом редакторе. На самом деле, эта же горячая клавиша доступна для целого ряда различных действий, например, когда вы ошибочно удалили ветку, допустили ошибку при операции слияния или закоммитили что-то в неправильной ветке.

Очистка истории коммитов


Во время работы над новой функциональностью «красота» вашей истории коммитов может не быть вашим главным приоритетом — и это понятно: есть много других забот. Но когда вы закончите работу и непосредственно перед тем, как объедините свой труд с веткой вашей команды, вероятно, будет хорошей идеей задержаться на мгновение, чтобы перевести дух.

Посмотрите на историю коммитов, которую вы создали, и подумайте, можно ли её улучшить: всё ли в ней легко читаемо и понятно? Есть ли коммиты, которые на самом деле не должны быть туда включены? Два коммита, которые следует объединить в один? Или огромный коммит-монстр, который следует разбить на более мелкие, более читабельные коммиты?

Очистка коммитов перед их интеграцией в командную ветку очень важна, особенно когда мы хотим поддерживать здоровую кодовую базу. И инструмент Git «Interactive Rebase» — идеальный способ добиться этого.

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

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

imageВыбор коммита для удаления из истории коммитов — например, если он содержит конфиденциальные данные

Чтобы исправить эту ошибку, мы инициируем сеанс Interactive Rebase, начиная с родительской ревизии ошибочного коммита:

git rebase -i 2b504be

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

imageПометив коммит при помощи drop, мы удалим его из истории

В нашем случае, поскольку мы хотим удалить коммит, просто помечаем соответствующую строку в редакторе ключевым словом drop. Как только мы нажмём «Сохранить» в редакторе и закроем окно, Interactive Rebase будет завершён — и ненужный коммит исчезнет!

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

imageУдаление коммита не повлияет на кодовую базу, но удалит его из истории.

Как уже упоминалось выше, Interactive Rebase может предложить гораздо больше вариантов использования! Если вы хотите узнать больше об Interactive Rebase и его возможностях, посмотрите бесплатную "Аптечку для Git": коллекцию коротких, полезных и бесплатных видеороликов, посвящённых устранению ошибок в Git.

Использование субмодулей для управления сторонним кодом


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

Теоретически вы можете просто скопировать и вставить необходимые файлы кода в свой проект, а затем зафиксировать их в своей базе кода. Но такой подход имеет несколько недостатков. Самое главное — вам будет очень трудно обновлять код сторонних разработчиков, когда появятся новые версии. Вам придётся снова скачивать код и копировать-вставлять его — снова и снова.

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

Гораздо лучше использовать структуру Git «Submodule»: это позволяет подключать сторонний код как Git репозиторий — внутри Git репозитория вашего реального проекта. Это означает, что все кодовые базы останутся аккуратно разделёнными.

Включить сторонний модуль/библиотеку так же просто, как выполнить следующую команду Git:

$ git submodule add https://github.com/djyde/ToProgress

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

Субмодули, признаться, довольно сложная тема, когда дело доходит до работы с ними на практике. Если вы хотите узнать о них поподробнее, ознакомьтесь с главой «Субмодули» бесплатной онлайн-книги «Learn Version Control with Git».

Генерируем коммиты с точностью


Существует золотое правило контроля версий: коммит должен содержать изменения только из одного выпуска! Когда вы придерживаетесь этого правила, вы создаёте коммиты, которые легко понять. В противном случае — когда в один коммит впихивается множество вопросов и тем — вы практически мгновенно создадите хаос в своей базе кода.

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

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

Вот тогда добавление полного файла в следующий коммит уже не является лучшей стратегией.

Staging выбранных частей ваших изменённых файлов


В примере ниже вы можете увидеть, что на данный момент у нас есть два чанка (= части или области) изменений в нашем файле imprint.html:

imageStaging выбранных частей ваших изменённых файлов

Предположим, что первый чанк принадлежит одной теме (возможно, мы находимся в процессе унификации и очистки всех заголовков страниц в нашем проекте). Также допустим, что второй чанк принадлежит другой, совершенно не связанной с ним теме.

Простой git add imprint.html, то есть добавление всего файла в Staging, сведёт все его изменения в один коммит. Тогда нашим коллегам будет трудно понять, о чём на самом деле был этот конкретный коммит. Увидев, что некоторые заголовки изменены, они могут подумать, что речь идёт только о «проекте по очистке заголовков», но они вполне могут пропустить другие изменения.

К счастью, Git позволяет нам точно выбирать чанки, которые мы хотим включить в следующий коммит! Всё, что нам нужно сделать, это добавить флаг -p к нашей команде git add:

$ git add -p imprint.html

imageТочный выбор чанков, которые мы хотим поместить в следующий коммит

Теперь Git берёт нас за руку и проводит по каждому чанку изменений в этом файле. И для каждого из них он задаёт нам простой вопрос: «Осуществить Stage для этого чанка?».

Давайте введём [Y] («Да») для первого и [N] («Нет») для второго. Когда мы затем действительно сделаем коммит, только первый фрагмент изменений будет включён. Второй останется как незафиксированное локальное изменение в нашей рабочей копии для последующего, отдельного коммита.

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

imageStaging и сброс чанков также возможен и в графическом интерфейсе

Повышение продуктивности работы с Git


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

Если вы хотите погрузиться в эту тему глубже, вот несколько полезных (и самое важное, бесплатных) ресурсов:

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

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


НЛО прилетело и оставило здесь промокоды для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.

20% на выделенные серверы AMD Ryzen и Intel Core HABRFIRSTDEDIC.

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


  1. Ritan
    18.02.2022 14:27
    +2

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

    А выпуск JIRA можно заполнить на закрепление этого переноса?


  1. vistar
    18.02.2022 15:03
    +3

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

    И сплошная реклама git tower. Чем он лучше остальных GUI?


    1. Conung_ViC
      18.02.2022 15:19
      +1

      Он еще и платный....

      так то мне для 99% ситуаций хватает встроенного в идею, бесплатной черепашки или в запущенных случаях - консоли...


      1. NickKolok
        19.02.2022 00:38

        Консоль + (в запущенных случаях) gitk

        Есть почти везде, работает предсказуемо. VSCode - не более чем для add и commit, на большее он не годен. Удобно, но только для этого.

        А вот молодёжь (20+-) и впрямь не может даже git clone сделать без IDE.


    1. NickKolok
      19.02.2022 00:38

      И ничего не под колпаком! Кто не верит - собират git сам из исходников!


  1. toxa82
    18.02.2022 17:16

    Вместо поиска по reflog сразу после reset --hard можно воспользоваться ссылкой на ORIG_HEAD: git reset ORIG_HEAD


  1. ALexhha
    18.02.2022 19:12
    +1

    Он еще и платный....

    При чем на самом сайте везде кричат Free. А как только начинаешь скачивать, то сразу - "Try Tower "Pro" for 30 days without limitations!" и уже как бы не совсем free


  1. noodles
    19.02.2022 11:34

    когда в один коммит впихивается множество вопросов и тем — вы практически мгновенно создадите хаос в своей базе кода

    не в базе кода, а в "кросоте" истории кода.. которая никому по факту не нужна.


    1. saidelman
      19.02.2022 12:17

      Всё-таки не стоит обобщать собственный опыт на всё человечество.


  1. ivanych
    19.02.2022 21:37

    Про субмодули совершенно невнятно написано. Что это, для чего, нафига включать чью-то репу внутрь своей?


    1. stanlyzoolo
      21.02.2022 10:16

      Категорически поддерживаю. Хотя бы привели пример в каких случаях применим такой подход.