В Playrix приходит много новых сотрудников и большинство из них не работали с Git. Особенно это касается гейм-дизайнеров и художников. Хотя и для программистов это не редкость – опыт работы с другими системами контроля версий не слишком помогает. Например, часто встречается опыт работы с SVN. Но Git заметно отличается по идеологии. Заучить, какие кнопки нажимать, в большинстве случаев не сложно, но шаг в сторону – и уже трудно понять, что происходит.



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

Глава 1. Первое знакомство


Представьте, что у вас есть каталог Work, в котором вы будете работать. Мы будем называть его рабочим каталогом. В нём лежит текстовый файл document.txt. Вы изо дня в день работаете с этим файлом, добавляете в него новый текст, ненужный удаляете, что-то изменяете. Внезапно вам потребовался текст, который вы пару дней назад удалили. Что делать? Если вы не используете систему контроля версий (СКВ), то этот текст не восстановить. А если вы пользуетесь СКВ – это не будет проблемой.

Как это работает? Вы всегда можете отправить свой файл в СКВ, и она его запомнит. Это называется «закоммитить файл» (команда commit). Если вы делаете такие коммиты после всех важных изменений файла, то внутри СКВ образуется множество копий разных его версий. Вы не увидите эти копии в вашем каталоге Work – там, по-прежнему будет лежать лишь один файл. Но все его копии, которые вы коммитили, можно при необходимости достать из СКВ. Там вы сможете посмотреть список всех версий вашего файла и проверить те строки, которые меняли в каждой версии. Удобно, не правда ли?

Предположим, вы меняете свой файл и даже сделали несколько его коммитов. СКВ запомнила закоммиченные версии файла (для краткости будем называть закоммиченную версию файла просто «коммитом»). Теперь выполним команду push – она отсылает ваши коммиты на сервер. В этом есть две главные цели:

  1. Сохранность (если у вас испортится компьютер, вся история изменений файла останется на сервере);
  2. Возможность нескольким людям одновременно работать над одним файлом.

Как выглядит одновременная работа? У других сотрудников на компьютере тоже есть папка Work и в ней тоже есть файл document.txt. Если вы отредактировали файл, сделали коммит и пуш, то ваши изменения попадут на сервер. Если другой человек выполнит команду pull, с сервера скачаются ваши изменения и человек увидит их в своём файле.

Так над одним и тем же файлом могут работать сразу несколько сотрудников. Они периодически забирают себе изменения других людей (pull), а также вносят свои изменения, коммитят их (commit), и отправляют на сервер (push). Оттуда их смогут забрать другие сотрудники.
Интересно, что команда pull скачивает с сервера не только последнюю версию файла, но и все предыдущие, которые кто-либо коммитил. То есть, все коммиты вашего коллеги будут храниться не только на его компьютере, но теперь и на вашем тоже. Благодаря этому можно просмотреть всю историю файла: кто, когда и какие строчки в нём менял.

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

Итоги:

  • Мы доверили Git следить за нашей рабочей папкой;
  • В папке есть текстовый файл, в котором работают наши коллеги;
  • Периодически мы забираем изменения других сотрудников в этом файле (команда pull);
  • А также мы сами меняем этот файл и делаем коммиты, позволяя Git запомнить новую версию файла. Потом мы отправляем наши коммиты на сервер (команда push). Отправлять можно как один коммит, так и сразу несколько. Но лучше пушить почаще, чтобы сотрудники видели актуальную версию файла. Другое дело, если работа не закончена — такую «рабочую» версию файла пушить, конечно, не стоит. Ведь вы создадите неудобства другим сотрудникам.

Убедитесь, что вы чётко поняли разницу между изменением файла, его коммитом и «пушем».
Поздравляем! Вы познакомились с основными возможностями системы контроля версий Git. Обратите внимание, мы специально не описываем, как вызывать команды. Потому что есть несколько Git-клиентов с разным интерфейсом. Чуть позже вы выберите один и изучите его. А пока мы просто расскажем, какие есть команды и что они делают.

Глава 2. Удалённый репозиторий, который никто не удалял


Место, куда Git сохраняет ваш файл после каждого коммита, называют локальным репозиторием. Он находится на вашем компьютере – потому и «локальный». Выше мы говорили, что команда push посылает ваши коммиты на сервер. Так вот, в Git не совсем верно говорить «сервер» – правильнее называть это «удалённым репозиторием». «Удалённый» – не потому, что его кто-то удалил, а потому, что он далеко (не у вас на компьютере). В нашем случае удалённый репозиторий находится на сайте GitHub. По своей структуре это такой же репозиторий, как у вас на компьютере. Он так же хранит коммиты. Команда push посылает коммиты с вашего локального репозитория в удалённый, а pull наоборот – забирает новые из удалённого репозитория в ваш локальный. Откуда там взялись свежие коммиты? Их туда отправили другие сотрудники.

Писать каждый раз «удалённый репозиторий» слишком долго. В Git его называют origin. Такова традиция. Дальше мы для краткости будем использовать термин origin вместо «удалённый репозиторий».

Глава 3. Углубляемся в детали


Пора углубиться в важные технические детали. Их довольно много, но понимание логики работы Git пригодится вам в работе. Так что придется набраться терпения.

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

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

Если вы добавили в ваш рабочий каталог новый файл и хотите, чтобы его тоже можно было коммитить (и чтобы его увидели другие сотрудники), вам нужно самому добавить файл в Git. Это делает команда add. Пока вы этого не сделали, Git не будет включать в коммиты ваш новый файл. Также можно создавать подкаталоги в рабочем каталоге. Файлы в них нужно добавить в Git тоже с помощью команды add.

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

Кстати, а откуда ваш рабочий каталог вообще возьмётся на вашем компьютере? Он там появится после того, как вы заберёте его с сервера (команда clone).

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

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

Перед тем, как сделать push (отправить коммиты в удалённый репозиторий origin), нужно обязательно сначала сделать pull (забрать последние изменения других людей, которые они отправили в origin). Если этого не сделать, система не даст вам выполнить push (появится сообщение об ошибке). Когда узнаете больше об особенностях работы Git, вы поймёте почему так происходит, а пока просто запомните это правило.

Глава 4. Незакоммиченные изменения


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

  • Если эти изменения не нужны, то можно отменить незакоммиченые изменения. При этом файл вернётся в состояние последнего коммита;
  • Если изменения полезные, то можно их закоммитить;
  • Ещё можно временно спрятать эти изменения (команда stash). При этом в рабочем каталоге ваши изменения откатятся. Позже вы сможете вернуть спрятанные изменения в рабочий каталог.

Глава 5. Конфликты и их разрешение


Когда вы забираете изменения из origin могут возникнуть конфликты. Это происходит, если:

  1. Вы изменили некоторые строчки в текстовом файле, закоммитили изменения, но ещё не сделали push.
  2. В это же время кто-то изменил эти же строчки в файле и успел отправить изменения в origin.
  3. Вы делаете pull, чтобы забрать чужие изменения. Git пытается объединить чужие изменения с вашими и обнаруживает, что изменены одни и те же строчки. Это называется конфликт (conflict).

Если это произошло, вам придётся разрешить конфликты вручную во всех файлах, где они возникли. Для каждой группы конфликтных строчек вы увидите два варианта – который написали вы и который написал кто-то другой.

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

Дальше повторяем такие же действия для каждой группы конфликтных строк в каждом файле, в котором есть конфликты.

Если конфликт не в текстовом файле, а в бинарном (например, картинка), то там никаких строчек, конечно, нет. Тогда нужно целиком выбрать какой из файлов оставить после слияния – вашу версию файла или чужую. Если вы не уверены, как правильно – свяжитесь с тем, кто менял этот файл последним (это можно узнать в истории изменений файла) и обсудите с ним чья версия файла должна остаться. Не стоит всегда брать свои версии не разобравшись – вдруг изменения другого человека правильнее. А вы их затрёте своими изменениями, если разрешите конфликт в свою пользу. Это явно будет нехорошо.

Когда все конфликты разрешены, можно продолжить операцию, которая была прервана из-за конфликта – обычно это операции pull, merge, rebase.

Если вас напугали конфликты и вы не готовы их разрешать прямо сейчас, можно выполнить команду abort. Она откатит состояние рабочего каталога – сделает его таким, каким он был до начала операции, которая вызвала конфликт.

Глава 6. Слепки


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

Представили? Назовём это состояние рабочего каталога «слепком». Каждый раз, когда вы делаете коммит очередных изменённых файлов, Git запоминает новый слепок (состояние всех файлов рабочего каталога). Понятие «слепка» мы будем использовать в следующей главе.

Примечание 1: Слепок – это НЕ состояние только лишь изменённых файлов. Это состояние ВСЕХ файлов рабочего каталога.

Примечание 2: Когда мы говорим «все файлы рабочего каталога», то, конечно, имеем в виду файлы под контролем Git. О всех остальных файлах Git ничего не знает.


Глава 7. История изменений и её визуальное представление


Историю изменений файлов рабочего каталога можно изобразить в таком виде:


Каждый кружок – это один коммит. На картинке показаны коммиты, которые сделаны один за другим. Это графическое представление истории коммитов.

Кстати, коммит можно рассматривать одним из двух способов:

  • Коммит, как изменение файлов с предыдущего коммита;
  • Коммит, как слепок – новое состояние всех файлов рабочего каталога, которое возникло после закоммиченных изменений.

В каких-то случаях удобно рассматривать историю, как цепочку изменений, а в каких-то – как цепочку слепков. Так что научитесь мысленно оперировать обоими вариантами.
Вот пример, когда удобно рассматривать «слепки». Представьте, что вы хотите посмотреть, как выглядел ваш рабочий каталог три коммита назад. Это легко устроить. Берём историю (см. картинку), отсчитываем 3 кружка (коммита) назад и говорим Git: «Хочу посмотреть, как выглядел рабочий каталог вот после этого коммита». Git изменит файлы в рабочем каталоге соответственно. Другими словами, мы переключили рабочий каталог на слепок этого коммита (или просто «на этот коммит»).
 
В следующей части статьи мы расскажем про:
 
  • Ветки
  • Слияние веток
  • Несколько мержей из ветки А в ветку В.
  • Мерж между ветками в обе стороны
  • Коммиты и их хеши
  • Ветки и указатели
  • Указатель head
  • Указатель origin\master

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


  1. Ivanq
    27.12.2017 17:21

    Прошу прощения, если прочитал по диагонали и не заметил, но. Не рассказано самое интересное — staging area. Во многих системах контроля версий индекса нет. То, как вы описали команду add скорее похоже на mercurial.


    В git никакие изменения сразу не регистрируются. Если вы изменили файл и запустили git commit, волшебство не произойдет. Вообще любые изменения нужно регистрировать git add — и создание, и изменение, и удаление файла. Изменения, добавленные git add — это и есть staging area. При это один файл может и быть, и не быть в staging area одновременно. Например (в консоли):


    $ vi file.txt
    $ git add file.txt
    $ vi file.txt
    $ git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
            modified: file.txt
    
    Changes not staged for commit:
      (use "git add/rm <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
      (commit or discard the untracked or modified content in submodules)
            modified: file.txt
    $ git commit # будет закоммичен первый файл

    Ну и естественно можно изменения из staging area удалить.


  1. RationalBot
    27.12.2017 18:18
    +1

    Стесняюсь спросить, а чем новых сотрудников не устраивают существующие учебники по git? Например, на git-scm (не сочтите за рекламу) есть версия на русском языке, доходчиво, с картинками.
    Почему-то этот момент упущен в мотивировочной части.


  1. savvadesogle
    27.12.2017 18:18

    Как ведёт себя гит с бинарными файлами? .pad, .jpg, .Avi и так далее? Есть ли специализированные системы контроля версий для не текстовых файлов?


    1. RationalBot
      27.12.2017 19:12

      С точки зрения хранения, git все равно, файл текстовый или нет. Я так понимаю, что вопрос про компактное хранение изменений в картинках? Я бы сказал, что для этого в первую очередь нужны тулзы, а не scm. Например, никто не мешает складывать в репозиторий транзакционные логи для базы данных. И потом ресторить актуальное состояние.
      Можно посмотреть в сторону файловых систем с де-дубликацией для эффективного хранения повторяющихся блоков данных (если они есть).


    1. DSolodukhin
      27.12.2017 22:18

      Для бинарных файлов в гит есть расширение Git LFS, в первую очередь направлено на оптимизацию хранения больших файлов, типа видео, аудио, изображений и т.д.


  1. webdevium
    27.12.2017 18:18

    Прошу прощения, но чем эта статья полезней других заметок в стиле «learn X in Y minutes»?


    1. dtyurev Автор
      27.12.2017 19:48

      Статей, в которых бы последовательно объяснялись идеи git (причём так, чтобы было понятно непрограммистам) не нашли. Если знаете такие, пришлите, пожалуйста, ссылки.


      1. webdevium
        27.12.2017 19:56

        Ну вот прям так, чтоб трехлетнему ребенку пояснить, да еще и чтоб он все понял — я и сам не встречал.
        Но простого howto должно быть достаточно. Не?
        Имхо, для непрограммистов нужны туториалы как пользоваться github for desktop или gitkraken. Им кнопочки нажимать нужнее, чем понимать что происходит под капотом.


      1. RationalBot
        27.12.2017 20:20

        Чуть выше я писал про git-scm.com/book/ru/v2


  1. Wolf4D
    27.12.2017 19:12

    Очень просто получить «быстрый старт» с чего-то, имеющего вменяемый и доступный GUI, типа SmartGit. Я вот начинал знакомство с системы контроля версий Mercurial, к которой по умолчанию прилагается неплохой такой GUI-клиент TortoseHg. Не пир духа, но, ИМХО, гораздо вменяемее «изкоробочного» git gui. ЕМНИП, покорило то, что диффы представлены в максимально наглядном (читай «и дураку понятном») виде, можно поправить файлы оттуда же перед коммитом, и, что особо ценно, можно откатить изменения одной-двух строк, а не всего файла.
    Когда я начал работать там, где Git был стандартом (и особо в чести была консольная работа с ним), то — после неудачного эксперимента по спариванию разных систем контроля версий при помощи бриджей (ещё то извращение, бррр!) — я долго выл на тему «изверги, неудобно же без визуальных плюшек!».
    А потом мне дали SmartGit. Он покрывает 95% джуновских потребностей в Гите и 60-70% потребностей сеньора. Сложные и замороченные вещи в нём делать сложно, зато простые вещи — очень и очень просто. Как показал опыт — новые бойцы втягиваются в Гит где-то после часа инструктажа по интерфейсу SmartGit, и новых проблем (при условии адекватности бойца) он сам по себе создавать не склонен. Рекомендую!


  1. iborzenkov
    27.12.2017 19:58
    +1

    Блин, где? Где вы до сих пор берете сотрудников которые работают с SVN а не с git?
    Я последний раз видел SVN когда с него мигрировали в 2011 году, после этого только git. Не, я понимаю дизайнеры, но их же обучат, у них программеры под боком, всегда найдется кто-то кто поможет если что.


    1. sav6622
      27.12.2017 20:01

      Встречаются и с CVS, и не пользовавшиеся SVN и GIT. Откуда — если привычный неосновной инструмент работает хорошо — зачем его менять ?


    1. skymal4ik
      28.12.2017 03:54

      Проверьте, их много… Это и энерпрайз, с огромным количеством коммитов и нежеланием тратить ресурсы на переезд на новую скв, и параноики, желающие иметь полный контроль над единственным репозиторием, и просто устаревшие и полу-актуальные проекты, которым это просто не нужно.
      Да что там… Я сам лично считал, что это просто хипстерская распиаренная поделка, пока не пришлось по работе изучить hg. И после личного контакта я понял, как ошибался, и побежал изучать git и переводить свои проекты с svn на него :)


    1. MacIn
      28.12.2017 18:00

      У нас SVN используется, перехода на git не предвидится — нет нужды в децентрализованной модели.


      1. sav6622
        28.12.2017 22:16

        Вам скоро будет радость — SVN начнет поддерживать локальные коммиты. Я, к сожалению, не дождался — сервис заломил приличные деньги за SVN репозитарии и я принудительно ушел на GIT (к моему удивлению он на амазоне бесплатный).


  1. aamonster
    27.12.2017 20:12

    Главный совет забыли: сразу найти человека, которому будете задавать вопросы.


    Наука умеет много гитик… То есть тьфу, git имеет много возможностей — и не меньше способов выстрелить себе в ногу. К примеру, я в начале пользования умудрился потерять ветку. Совсем — так что при просмотре дерева ревизий её не было. К счастью, немного гугления, чтения док — и я освоил git reflog и шаманство с git branch (после mercurial с его "history is permanent and sacred" это был шок).


    1. Beholder
      28.12.2017 15:17

      В Mercurial rebase и другие команды модификации истории есть давным-давно.


      1. aamonster
        28.12.2017 15:25

        Знаю, даже пользуюсь дома (хотя и с осторожностью, обычно предпочитая бранчи). Но даже с учётом этих команд — mercurial заметно проще, а "святость истории" навязывается гораздо сильнее, чем в git.


  1. RomanPokrovskij
    27.12.2017 21:12

    Сразу скажу, что я не уверен в чистоте своих впечатлений, но вообще понимание git мне пришло с пониманием того что никакого чуда нет, в конце концев рекомендуемая модель (GIT_Succinctly стр 58) — Integrator Workflow, когда хоть изменения пулятся в общий паблик репоситорий, мержатся они должны в другом «архитекторском» и только «архитектор» будет мержить изменения в «публичный» паблик.

    Правда как они перенаправляются из публичного в архитекторский — до сих пор не понятные мне детали (объясните?)… Но главное, что «по краям» возможности системы очерчены.


  1. KeyJoo
    28.12.2017 00:39

    Отпишусь, как новичёк по данной теме.
    Смотрел
    [x] на Ютьюбе несколько видеороликов, по 5 минут,
    [x] несколько статей прочитал.
    Уже несколько дней работаю с гитом через консоль, хотя ранее использовал GUI-software.


    $ git branch
    * develop
      feature
      hotfixes
      master
      release

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


  1. Hesed
    28.12.2017 00:52

    Вполне неплохой мануальчик для начинающих, буду и сюда отправлять тех, кто хочет, чтобы за ручку привели и книжку дали. В коллекцию полезных ссылок добавлю: http://ohshitgit.com/ как разрулить частые «ой, блин» в гите.


  1. da-nie
    28.12.2017 14:12

    О, может кто подскажет.
    Я использую GIT-GUI. Вот наделал я набор коммитов. И хочу вернуться назад к какому-то варианту. Выбираю репозиторий->показать историю ветви. А вот дальше, если я выберу что-либо и нажму установить ветвь на это состояние, то файлы изменяются, только если сделать вариант «жёсткий». Но при этом все коммиты ветки после выбранного коммита нафиг теряются. Как же тогда делать в git-gui такой переход?
    Ну и второй вопрос — нет ли у кого работающего GIT под QNX? Тот, что я видел не работал нифига. Команды ничего не делают.
    Спасибо.


  1. Arxitektor
    28.12.2017 19:26

    Идиотский вопрос а чем Git отличаеться от github?
    Сам Git это системами контроля версий а github это облачный репозиторий который работает на Git?


    1. lexxpavlov
      29.12.2017 09:31

      Git и Github — это как котлета и кот, который её ест…


    1. RomanPokrovskij
      29.12.2017 13:24

      облачный репозиторий + постоянно наращиваемый web аpp (в git нет issues, releases и т.д)


    1. DSolodukhin
      29.12.2017 22:15
      +1

      Примерно тем же, чем отличается email и Mail.ru.