git - направления изучения
Данный документ по смыслу находится где-то между аннотацией и экзаменационными билетами. Мы попытались описать все нужные нам концепции git кратко и понятно, не давая технических деталей, и указать направления изучения. Далее следуют умения, которыми нужно овладеть.
Инструмент для хранения истории изменения файлов в директории (папке), над которой работает один или более человек.
Репозиторий git - это папка, содержащая файлы и подпапки, со специальной подпапкой .git. Подпапка .git управляется только посредством команд git и хранит служебные данные об истории изменений в папке.
- запоминать состояние папки, т.е. состав файлов и подпапок и их содержимое
- вести историю таких запомненных состояний
- назначать имена состояниям (сообщения фиксации, ветки и метки)
- синхронизировать историю изменений с другими копиями этого же репозитория, возможно, находящимися на других компьютерах
- уметь восстанавливать любое из запомненных состояний
- отвечать на вопросы о состоянии и истории папки, например, показывать разницу между состояниями
Можно иметь много разных копий репозитория на разных компьютерах. Есть команды для обмена информацией между этими репозиториями. Может получиться, что два пользователя в разных копиях репозитория внесли противоречащие друг другу изменения по отношению к начальному состоянию, в этом случае git предоставляет инструменты разрешения конфликтов.
Доступ к репозиторию может осуществляться через веб-интерфейс, например, можно разместить копию репозитория на сайте gitlab.com и использовать её в качестве основной копии, а для работы над изменениями копировать репозиторий с gitlab.com на локальный компьютер. При этом доступны дополнительные возможности:
- просмотр изменений и истории состояний в графическом виде
- разграничение прав доступа к командам
- выполнение скриптов при внесении изменений
Есть также графические интерфейсы к git, запускаемые на локальной машине, например, gitk. Также среды разработки (например, VS Code) частично поддерживают работу с git.
Коммит - это запись об изменении состояния папки. Коммит содержит в себе полную информацию о состоянии всех файлов в папке, кроме не добавленных, служебных и игнорируемых.
- Служебные файлы - это подпапка .git. Файлы в этой папке хранят историю изменений остальных файлов.
- Игнорируемыеы файлы перечислены в файле .gitignore (или многих файлах .gitignore, расположенных в разных местах). git не видит эти файлы и не отслеживает изменения в них.
- Не добавленные файлы - файлы, которые не являются служебными и игнорируемыми, но про которые пользователь не сказал, что их состояние нужно отслеживать. Гит постоянно напоминает про этих файлах в отчёте о состоянии, но он не записывает их состояние в коммит.
Родители - это один или более коммитов. Обычно у коммита один родитель и это - предыдущее запомненное состояние папки. Но бывает более одного родителя
Может получиться, что из данного состояния возникло более одного будущего состояния.
Например, так:
- Вася 1 февраля начал в своём репозитории работу над задачей "новая глава" с состояния, названного "вечер_31"
- Вечером он 1 февраля Вася не закончил работу и сохранил промежуточный результат под именем "вечер_1"
- Утром 2 февраля выяснилась досадная ошибка в ранее сделанной работе, которую нужно срочно починить. Вася вернул папку к состоянию "вечер_31" (работа за 1 февраля сохранена в репозитории, т.е. в спец.папке .git)
- Вася решил срочную задачу, сделал коммит (запись) под именем "аврал_починка" и сдал.
- 3 февраля Вася хочет вернуться к работе над задачей "новая глава", но нужно учесть и результаты аврала-починки. В этой ситуации Васе понадобится "слить ветки".
Более частая ситуация, когда нужно сливать изменения - это когда над проектом работают более одного человека.
git старается, чтобы ничьи изменения не пропали зря. Например, если при слиянии в обеих сливаемых версиях будет изменена одна и та же строка какого-то текстового файла, то это называется конфликт изменений. git помечает такие строки особым образом и отказывается сливать изменения. Нужно отредактировать файлы, далее указать, что конфликт улажен, и только после этого будет возможно завершить слияние.
- У каждой записи (коммита) есть своё "сообщение фиксации", которое говорит о том, какое последнее изменение было сделано. Его нужно аккуратно заполнять, чтобы через время оставалось понятным, что и когда менялось в репозитории, без детального изучения всех изменений.
- ветка - это "версия истории". В каждый конкретный момент ветка указывает на какой-то коммит. В репозитории есть понятие текущей ветки, можно узнать его (например, с помощью git status). При записи изменений (коммите) текущая ветка перемещается и начинает указывать на последнее сделанное изменение. Но можно переставить ветку, чтобы она указывала на другой коммит. Ветки можно передавать по сети между разными копиями репозитория. При слиянии указываются именно ветки, а не просто состояния (коммиты), потому что мы сливаем не конкретные изменения, а целые истории изменений, в которых может быть много последовательных состояний.
- метка также указывает на какой-то коммит, но она проще, чем ветка - при добавлении новой записи она никуда не перескакивает. Меткой можно помечать, например, публичную версию программы, которую мы рекомендуем для скачивания.
Внесение изменений состоит из двух этапов: сначала изменения вносятся в так называемый индекс, по английски это называется "staged". Эти изменения ещё не записаны в историю и они не передаются по сети при обмене данными с другими репозиториями. Далее изменения заносятся непосредственно в историю команд. Желательно не держать изменения в состоянии staged длительное время. Самое частое применение промежуточного staged состояния - это когда внесены изменения во множество разных файлов в папке, и мы хотим это оформить в виде нескольких отдельных коммитов (записей о состоянии), чтобы потом было легче понять логику наших изменений.
Не пользуйтесь им
Вопрос о том, какие файлы хранить в репозитории, а какие нет - сложный вопрос. Например, не всегда очевидно, хранить ли в репозитории скомпилированную программу? гит плохо хранит большие двоичные файлы. Для этой цели есть git lfs, но не пользуйтесь им.
Зачастую проекту нужны какие-то другие репозитории git (например, библиотеки), которые тоже меняются во времени. Для того, чтобы запомнить состояние этих сторонних репозиториев, используются подмодули git.
- https://git-scm.com/book/ru/v2
- https://stepik.org/course/4138/promo
- https://stepik.org/course/3145/promo
Мы ожидаем, что Вы закончите обучение в течение двух недель. По результатам обучения мы зададим вопросы по затронутым здесь темам и попросим Вас показать на нашей машине практическое владение git.
- Установите MSYS2, напр, по этой инструкции
- Запустите MSYS2 MinGW 64 bit
- Установите git и gitk
- Поставьте по инструкции VS Code
- установите любой графический рабочий стол
sudo apt install git gitk
- поставьте по инструкции VS Code
- Создайте учётную запись на gitlab.com
- установите русский язык интерфейса
- создайте новый пустой проект
- склонируйте его на свой компьютер, следуя инструкциям на сайте
- в копии репозитория на вашем компьютере делайте изменения (добавление или изменение текстовых файлов)
- индексируйте изменения, отменяйте индексацию
- фиксируйте их с помощью команд git add, git commit
- отправляйте изменения на gitlab.com
- вернитесь к предыдущему состоянию с помощью git checkout
- просматривайте историю с помощью gitlab и gitk
- создавайте новую ветку из старого состояния
- вносите изменения в новую ветку, без конфликта
- слейте ветки
- откройте Ваш проект в vs code,
- сделайте изменения в файлах с помощью gitlab
- сделайте запись о состоянии (коммит)
- отправьте его на gitlab
- просмотр истории файла в gitlab
- показать автора данной строки (blame) в gitlab
Этот пункт не обязателен, но его выполнение - это большой плюс.
- создайте две версии истории, чтобы возник конфликт
- объедините ветки, разрешив конфликт. Под Linux можете попробовать использовать git mergetool (kdiff3). Под Windows придётся править файл вручную.