К содержимому
ИС30

Поиск по сайту

Конспекты, лабы, квизы, ЧаВо и страницы

Войти

Лекция 1. Системы контроля версий и Git

Зачем нужен контроль версий, история от SCCS до Git, централизованная и распределённая модели, устройство Git, первые команды, гигиена коммитов, ветки, слияние и конфликты, откат, Git Flow.

Первая лекция курса: откуда взялся контроль версий, чем распределённая модель Git отличается от централизованных систем и как выглядит базовый рабочий цикл в консоли — от git init до слияния веток и разрешения конфликтов. Лекция заканчивается договорённостями о ветках в команде (Git Flow).

Как учить

Понятия коммит, ветка и слияние одинаковы во всех системах контроля версий, отличаются только команды. Освойте консольный Git: IDE прячет часть действий, а на работе руками делать всё равно придётся.

1. Вступление: здесь не школа

  • Лектор не может долго говорить, поэтому лекции, скорее всего, будут заканчиваться раньше полутора часов.
  • За студентами никто бегать не будет. В прошлом году мамы первокурсников создали «родительский комитет» и пришли в деканат жаловаться, что практик не ставит лабы; их отправили обратно. Здесь каждый сам отвечает за свои поступки.
  • Около 20 % покидают университет после первого семестра: академ или отчисление. Не потому что преподаватели злые, а потому что ребята не поняли, куда попали. Программа стала заметно сильнее.
  • Практики — работающие люди, не штатные сотрудники университета, платят им немного. Если не учиться самому, ни лектор, ни практики не помогут.
  • Сакральных знаний на лекциях нет: всё есть в интернете и на YouTube. Лекция — один из способов получить информацию, не единственный.
  • Первые два семестра нужно выжить, дальше легче.

2. Зачем нужен контроль версий

  • Контролем версий пользовались все: «документ», «документ 1», «финал», «финал-финал». Пока файл один и работаете вы один, это терпимо.
  • С кодом иначе: файлов много, изменения несколько раз в день. Нужно знать, где и что менялось, и уметь откатить одно изменение, сохранив остальные.
  • Проблема поставлена не вчера: первая система контроля версий появилась в 1972 году.

3. История: централизованные системы

ГодСистемаЧто нового
1972SCCS, Bell Labs (Марк Рочкинд)первая система; инструмент одиночного разработчика; наружу из Bell Labs не вышла
1982RCSпервая общедоступная; всё ещё для одного человека
1986CVSклиент-серверная модель, фиксация изменений (check-in, будущий коммит) и откаты; позже в том же духе — Subversion (SVN)

В 1972 году командной разработки, тимлидов и Agile не было: код писали «супермонстры», совмещавшие аналитика, разработчика и тестировщика, в основном на ассемблере и C.

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

Достоинства (думайте как начальники):

  • Безопасность: разработчик видит только свой кусок, при компрометации его учётки весь проект не утечёт. Для сравнения: игры сейчас утекают целиком за неделю до релиза.
  • Контроль: админ видит, кто сколько и куда закоммитил, кто работает, а кто нет.
  • Одна точка администрирования.

Недостатки:

  • Медленно: каждая операция идёт через сервер.
  • Согласованные изменения в разных модулях (клиент и сервер) одному разработчику не видны целиком, ошибки всплывают при слиянии.
  • Весь продукт контролирует один человек, который нарезает код; таких людей мало и стоят они дорого.
  • Нужна сеть с толстым каналом: в 1986 и даже в 2000 году работать можно было только в офисе.
  • Единая точка отказа: пожар или потоп — и сервер потерян. Пример из начала 2000-х в районе Невской Дубровки: RAID уже был, но серверная сгорела, и данные пропали.

4. Git и распределённая модель

  • В 2005 году Линус Торвальдс написал Git для разработки ядра Linux: над ядром работало распределённое сообщество, и схема с одним админом ему не подходила.
  • Каждый разработчик клонирует полную копию репозитория и работает в ней. Сливаться в центральный репозиторий нужно не в конце дня, а когда задача решена.
  • Дальше начинаются гонки: кто первым запушил, у того проблем нет; остальные накладывают свои изменения поверх чужих и получают конфликты слияния.
  • Квалификация разработчиков нужна заметно выше: в централизованной модели можно было набирать дешёвый аутсорс, здесь нужны люди, понимающие проект целиком.
  • Появился GitHub, и Git стал стандартом индустрии.

Недостатки распределённой модели:

  • Безопасность: у каждого полная копия. Компании заставляют подписывать бумагу об ответственности за ноутбук: не оставлять в кафе, на заправке, на заднем сиденье машины.
  • Хранение: у каждого вся история, а это обычно старый проект с огромным числом коммитов.
  • Закладки: в распределённой команде один человек может внести бэкдор, и без ревью и автоматических проверок он попадёт в проект. После 2022 года выяснилось, что многие open-source компоненты, которыми пользуется промышленность, содержали скрытую функциональность. Отсюда требования: обязательное ревью и пайплайн с проверками.
  • Нужна культура: дисциплина ложится на команду, а не на сервер.
  • Неявный минус: раньше в 8–10 вечера закрывали ноутбук и уходили домой, теперь можно коммитить в полночь с дачи.
Git только для текста

Бинарные файлы (картинки, собранные библиотеки, исполняемые файлы) Git хранит плохо: не умеет считать разницу между версиями и кладёт файл целиком при каждом коммите. Такие файлы перечисляют в .gitignore — списке того, что не должно попадать под контроль версий.

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

5. Как Git устроен внутри

  • Добавленные файлы сжимаются алгоритмом zlib (тот же, что в zip). Текст сжимается отлично, поэтому Git и заточен под текст.
  • От сжатого содержимого считается хэш SHA-1, он становится уникальным идентификатором объекта.
  • При создании Git считали, что длины SHA-1 хватит навсегда, как когда-то «одного мегабайта памяти хватит всем». По словам лектора, в старых проектах с огромным числом коммитов случаются коллизии, и там увеличивают длину ключа.
  • Первая версия файла хранится полностью, дальше фиксируются только изменения: что добавили, что убрали. При переключении на другой коммит Git убирает из рабочей папки текущий файл и распаковывает нужную версию.

6. Первые команды

Два способа начать работу на локальной машине:

git init            # новый проект с нуля, «сразу по-правильному»
git clone <url>     # клонировать готовый репозиторий: настройки уже сделаны, init не нужен

На работе, скорее всего, выдадут станцию с уже установленным Git. На Windows Git ставится со своей консолью; есть графические клиенты и интеграция в IDE, но базовые команды нужно знать.

git status                  # состояние репозитория
git add <файл>              # взять файл под контроль; можно по маске *.txt, папку или всё сразу: git add .
git commit -m "сообщение"   # зафиксировать добавленные файлы в текущем состоянии
git log                     # история коммитов
  • Новый файл в git status показан как untracked: Git его не отслеживает, файл можно менять и удалять, Git не заметит. После git add файл отслеживается, но состояние ещё не зафиксировано — для этого нужен коммит.
  • При git init создаётся одна ветка, master. В новых версиях ветка по умолчанию называется main, старые репозитории просят переименовать. Ветку можно создать только от коммита, поэтому сначала нужны коммиты.

7. Гигиена коммитов

  • У коммита обязательно есть сообщение, и это не набор букв: «добавил новый файл», «изменил содержимое». В корпоративной разработке — номер тикета: «задача выполнена в рамках тикета такого-то».
  • Через 3–6 месяцев вы вернётесь к проекту и увидите историю из бессмысленных сообщений — придётся вспоминать, что делали.
  • CI/CD-системы парсят сообщения: увидев номер тикета, подтягивают сценарий и запускают автосборку. Мусор в сообщении — сборка не запустится.
  • Git персонифицирован: каждый коммит подписан именем и email, по каждому багу можно найти автора. Без этой настройки первый коммит не создастся:
git config --global user.name "Имя Фамилия"
git config --global user.email "you@company.com"

Корпоративный ящик — для работы, личный — для своих проектов.

8. Ветки

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

git branch lesson && git checkout lesson   # создать ветку и переключиться, два шага
git checkout -b lesson                     # то же одной командой
  • Сразу после создания master и новая ветка указывают на один и тот же коммит.
  • Демо: в новой ветке добавили файл и закоммитили, переключились на master — файл исчез: Git убрал файлы ветки и распаковал последний коммит master. Так команды не мешают друг другу.
  • IDE делает add и commit одной кнопкой, но это два действия.

9. Слияние и конфликты

git checkout master
git merge lesson     # влить ветку lesson в master
  • Обычно команды пишут разные файлы, и слияние проходит автоматически: в 95 % случаев auto-merge отрабатывает.
  • Если два человека правили одно место одного файла, возникает merge conflict. Бояться не нужно: Git сообщает, что автоматическое слияние не отработало, и человек разрешает конфликт руками.
  • В файле появляются маркеры: между <<<<<<< HEAD и ======= ваш вариант, между ======= и >>>>>>> lesson входящий. Оставляете нужное, убираете маркеры.
  • После разрешения конфликта коммит не появляется сам: нужны git add и git commit.
  • После merge обе ветки продолжают существовать: можно работать в ветке дальше и сливать ещё раз.
  • В реальности слияние в основную ветку делает тимлид, поэтому в GitHub и GitLab есть pull request / merge request: вы открываете запрос, лид проверяет, потом решаете вместе.

10. Откат

  • На последний коммит указывает HEAD. Откатиться на NN коммитов назад можно без хэша: git reset HEAD~N; журнал всех перемещений HEAD показывает git reflog, и на его записи тоже можно откатываться.
  • Отменять коммиты можно, только пока они не отправлены на удалённый сервер. После push историю не переписывают: идёте к старшим, «ребята, я накосячил, помогите».

11. Бинарники: SVN против Git

Subversion спокойно хранит бинарники, и при переходе с SVN на Git по привычке заливали картинки и документацию. В Git каждый коммит с бинарником кладёт файл целиком: проект на 10 гигабайт, три коммита — три копии.

12. Как работать с ветками

  • Ветки использовать обязательно. Когда все коммитят в main, непонятно, кто что и зачем сделал.
  • Работайте в ветке: боитесь потерять данные — делайте хоть сто коммитов, потом один merge. В main остаются два коммита: начальный и коммит слияния. Основное тело продукта чистое, его можно отдавать заказчику и коллегам.
  • Ветка остаётся локальной, отправлять её на сервер не обязательно. Удалить: git branch -d lesson (-D — принудительно).
  • После удаления ветки коммиты никуда не деваются: зная хэш, можно сделать checkout на коммит и продолжить от него. Лектор проверял, работает, но делать так не рекомендует.

13. Соглашения в команде: Git Flow

  • Собрали команду — договоритесь, как вести контроль версий и называть ветки. Общепринятых схем несколько; на лекции разобран Git Flow, который покрывает около 80 % случаев.
  • Основная ветка — develop. В неё попадают только финальные сборки по версиям (v1, v2 и так далее), любые другие коммиты туда запрещены.
  • Ошибка в конкретной сборке: от нужного коммита создаётся ветка hotfix, там исправляется эта сборка, исправление вливается обратно.
  • Фичи, патчи и баги делаются в отдельных ветках. Разработчик закончил ветку — слил её; раз в месяц всё собирают вместе и получают релиз.
  • Заказчик видит чистую историю релизов и никогда не видит develop с патчами. Что происходит на вашем компьютере, никого не волнует: ветвитесь как хотите, главное донести до релиза чистую историю.
  • Антипример: компания на контракте должна была выпускать продукт раз в месяц. Новички заводили ветку на каждую задачу и никогда их не сливали. В итоге «продукт 1, 2, 3, 4», и релиз раз в месяц стал невозможен.

14. Зачем поддерживать старые версии

  • Выпустили пять версий, что-то падает, простой приносит убытки — нужно срочно вернуться на три версии назад. Или после второй версии нашли бэкдор.
  • На практике никто не ставит последнюю версию: выкатили в декабре новую ERP, и ни один IT-директор не рискнёт местом, чтобы её поставить. Один заказчик сидит на одной версии, два других — на другой.
  • Приходит заказчик с деньгами: «всё новое не надо, но в пятой версии добавили поддержку iOS, сделайте мне её в мою версию». Тогда от его версии делается ветка, и iOS добавляется туда. Это коммерческая разработка.

15. Вопрос из зала: почему не собирается

Файлы .cpp компилируются в объектные файлы, затем линкуются в исполняемый. Если старый исполняемый файл в этот момент запущен, он занят, и линкер не сможет записать новый на его место — сначала закройте программу. В IDE конфигурации debug и release собирают разные исполняемые файлы: проверьте, какую конфигурацию запускаете.

Частые ошибки

  1. Бессмысленное сообщение коммита. Через полгода не вспомните, что делали, а CI не найдёт номер тикета.
  2. Коммит без настроенных user.name и user.email. Первый коммит просто не создастся.
  3. Бинарники в репозитории. Каждый коммит хранит файл целиком; пишите такие файлы в .gitignore.
  4. Работа прямо в main. История захламляется, непонятно, кто что сделал; работайте в ветке и сливайте одним merge.
  5. Переписывание истории после push. Отменять коммиты можно только локально; после отправки — только вместе со старшими.
  6. Забытый коммит после разрешения конфликта. Маркеры убраны, но нужны ещё git add и git commit.
  7. Считать add и commit одним действием. IDE делает их одной кнопкой, но это два шага.

Мини-тренажёр

  1. Чем клон (git clone) отличается от git init?
  2. Файл показан как untracked. Что это значит и какая команда это изменит?
  3. Почему Git плохо хранит картинки и что с этим делать?
  4. Перечислите две команды, без которых не создастся первый коммит.
  5. После git merge в файле появились маркеры <<<<<<< и >>>>>>>. Что делать по шагам?
  6. В какую ветку по Git Flow попадают только финальные сборки и где чинят ошибку конкретной сборки?
  7. Почему после удаления локальной ветки коммиты не пропадают?
Ответы
  1. git clone копирует готовый репозиторий с уже сделанными настройками, git init создаёт пустой репозиторий с нуля.
  2. Git не отслеживает файл: изменения и удаление не заметит. git add <файл> берёт его под контроль.
  3. Git не умеет считать разницу между версиями бинарника и кладёт файл целиком при каждом коммите; такие файлы перечисляют в .gitignore.
  4. git config --global user.name "…" и git config --global user.email "…".
  5. Выбрать нужный вариант между маркерами, удалить маркеры, затем git add и git commit.
  6. В develop; ошибку чинят в ветке hotfix, созданной от коммита нужной сборки, и вливают обратно.
  7. Ветка — только указатель на коммит; сами коммиты остаются в репозитории, и зная хэш, на них можно сделать checkout.

Шпаргалка

ЗадачаКоманда
Начатьgit init или git clone <url>
Представитьсяgit config --global user.name "…", git config --global user.email "…"
Что происходитgit status, git log
Взять под контрольgit add <файл>, git add .
Зафиксироватьgit commit -m "что сделано"
Веткаgit checkout -b lesson; удалить git branch -d lesson
Переключитьсяgit checkout master
Слитьgit merge lesson, конфликт разрешить руками, затем add и commit
Откатить локальноgit reset HEAD~N, история перемещений git reflog
Не хранитьбинарники и артефакты сборки — в .gitignore
Git Flowdevelop только для релизов; фичи, баги, hotfix — в отдельных ветках

Проверь себя

12 вопросов по материалу лекции. Результаты хранятся только в вашем браузере.

Двенадцать вопросов по лабораторной работе по Git: клонирование, ветки, коммиты, просмотр истории и изменений.

  • 12 вопросов
  • Результат виден сразу после каждого ответа
  • Порядок вопросов случайный

Комментарии0

Пока никто ничего не написал.

Войдите, чтобы оставить комментарий