Мастер-класс по Git
О работе
В данной работе предстоит:
- Познакомиться с основами Git.
- Создать репозиторий в GitLab и склонировать.
- Выполнить действия по управлению репозиторием.
Часть 0. Установка Git
Установка Git на Windows
Статья основана на "Install Git" и "Download for Windows".
Шаги установки
- Загрузите последнюю версию установщика Git для Windows.
- После успешного запуска программы установки вы должны увидеть экран мастера настройки Git. Следуйте инструкциям
Next
иFinish
, чтобы завершить установку. Параметры по умолчанию довольно понятны для большинства пользователей. - Настройте имя пользователя и адрес электронной почты в Git, как показано в статье "Настройки Git" из данного руководства.
Установка Git на Linux
Статья основана на "Install Git" и "Download for Linux and Unix".
Возможно, в вашем дистрибутиве git уже установлен. Чтобы узнать, откройте терминал и введите
git --version
Проще всего установить Git в Linux, используя предпочтительный менеджер пакетов вашего дистрибутива Linux. Если вам требуется более свежая версия Git или он по какой-то причине отсутствует в вашей операционной системе, то следуйте указаниям ниже.
Шаги установки
- Установите Git согласно инструкциям, указанные в статье "Download for Linux and Unix".
- Настройте имя пользователя и адрес электронной почты в Git, как показано в статье "Настройки Git" из данного руководства.
Установка Git на macOS
Статья основана на "Install Git" и "Download for macOS".
Существует несколько способов установки Git на Mac. На самом деле, если вы установили XCode (или его инструменты командной строки), Git, возможно, уже установлен. Чтобы узнать, откройте терминал и введите
git --version
Apple на самом деле поддерживает и поставляет свою собственную версию Git, но она, как правило, отстает от основной версии Git на несколько основных версий. Если вам требуется более свежая версия, то следуйте указаниям ниже.
Шаги установки
- Установите Git согласно инструкциям, указанные в статье "Download for macOS".
- Настройте имя пользователя и адрес электронной почты в Git, как показано в статье "Настройки Git" из данного руководства.
Часть 1. Основы Git
Управление исходным кодом
Управление исходным кодом (англ. source control management, SCM) используется для отслеживания изменений в репозитории исходного кода. SCM отслеживает текущую историю изменений в базе кода и помогает разрешать конфликты при объединении обновлений от нескольких участников.
Репозиторий — место, где хранятся и поддерживаются какие-либо данные. Чаще всего данные в репозитории хранятся в виде файлов, доступных для дальнейшего распространения по сети. Также под репозиторием понимается каталог файловой системы, в котором могут находиться файлы журналов конфигураций и операций, выполняемых над репозиторием, а также сами контролируемые файлы.
Git-репозиторий (источник: learn.microsoft.com):
По мере роста количества строк кода и количества участников программных проектов растут и затраты на коммуникационные издержки, а также сложность управления. SCM является важнейшим инструментом для облегчения организационной нагрузки, связанной с растущими затратами на разработку.
Важность инструментов управления исходным кодом
Когда несколько разработчиков работают в рамках общей кодовой базы, внесение изменений в общий фрагмент кода является обычным делом. Отдельные разработчики могут работать над, казалось бы, изолированной функцией, однако эта функция может использовать общий модуль кода. Поэтому разработчик №1, работающий над функцией №1, может внести некоторые правки и позже выяснить, что разработчик №2, работающий над функцией №2, имеет конфликтующие правки.
В интересах кого SCM работает (источник atlassian.com/git):
До принятия SCM это был кошмарный сценарий. Разработчики будут редактировать текстовые файлы напрямую и перемещать их в удаленные места с помощью FTP или других протоколов. Разработчик №1 внесет изменения, а разработчик №2 неосознанно сохранит работу разработчика №1 и уничтожит изменения. Роль SCM как механизма защиты от этого конкретного сценария известна как контроль версий.
SCM внедрила меры контроля версий для предотвращения потери работы из-за перезаписи конфликта. Эти меры предосторожности работают путем отслеживания изменений от каждого отдельного разработчика, выявления конфликтных областей и предотвращения перезаписи. Затем SCM сообщит об этих конфликтных моментах разработчикам, чтобы они могли безопасно просмотреть и устранить.
Взаимодействие в команде разработки (источник atlassian.com/git):
Этот основополагающий механизм предотвращения конфликтов имеет побочный эффект, заключающийся в обеспечении пассивной коммуникации для команды разработчиков. Затем команда может отслеживать и обсуждать текущую работу, которую отслеживает SCM. SCM отслеживает всю историю изменений в базе кода. Это позволяет разработчикам изучать и просматривать правки, которые могли привести к ошибкам или регрессиям.
Преимущества управления исходным кодом
В дополнение к контролю версий SCM предоставляет набор других полезных функций, которые делают совместную разработку кода более удобной для пользователя. Как только SCM начинает отслеживать все изменения в проекте с течением времени, создается подробная историческая запись жизненного цикла проекта. Эта историческая запись затем может быть использована для ‘отмены’ изменений в кодовой базе. SCM может мгновенно вернуть кодовую базу к предыдущему моменту времени. Это чрезвычайно важно для предотвращения регрессий при обновлениях и устранения ошибок.
- Архив SCM всех изменений за время существования проекта обеспечивает ценный учет примечаний к выпускной версии проекта. Чистый и поддерживаемый журнал истории SCM можно взаимозаменяемо использовать в качестве примечаний к выпуску. Это обеспечивает понимание и прозрачность хода выполнения проекта, которыми можно поделиться с конечными пользователями или командами, не занимающимися разработкой.
- SCM сокращает коммуникационные издержки команды и увеличит скорость выпуска. Без SCM разработка идет медленнее, потому что участникам приходится прилагать дополнительные усилия для планирования непересекающейся последовательности разработки для выпуска. С помощью SCM разработчики могут независимо работать над отдельными разделами разработки функций, в конечном итоге объединяя их вместе.
Коммуникация в команде разработки (источник atlassian.com/git):
В целом SCM - это огромная помощь инженерным командам, которая позволит снизить затраты на разработку, позволяя инженерным ресурсам работать более эффективно. SCM - это обязательное условие в современную эпоху разработки программного обеспечения. Профессиональные команды используют контроль версий, и ваша команда тоже должна это делать.
Вывод
SCM - бесценный инструмент для современной разработки программного обеспечения. Лучшие команды разработчиков программного обеспечения используют SCM, и ваша команда тоже должна. SCM очень легко настроить в новом проекте, а отдача от инвестиций высока.
Что такое Git и зачем он нужен?
Основано на статье Git для новичков (часть 1) | Habr.
Git - это консольная утилита, для отслеживания и ведения истории изменения файлов, в вашем проекте. Чаще всего его используют для кода, но можно и для других файлов. Например, для картинок - полезно для дизайнеров.
С помощью Git-a вы можете откатить свой проект до более старой версии, сравнивать, анализировать или сливать свои изменения в репозиторий.
Репозиторием называют хранилище вашего кода и историю его изменений. Git работает локально и все ваши репозитории хранятся в определенных папках на жестком диске.
Так же ваши репозитории можно хранить и в интернете. Обычно для этого используют три сервиса:
Каждая точка сохранения вашего проекта носит название коммит (commit). У каждого commit-a есть hash (уникальный id) и комментарий. Из таких commit-ов собирается ветка. Ветка - это история изменений. У каждой ветки есть свое название. Репозиторий может содержать в себе несколько веток, которые создаются из других веток или вливаются в них.
Базовые понятия
Репозиторий – папка проекта, отслеживаемого Git, содержащая дерево изменений проекта в хронологическом порядке. Все файлы истории хранятся в специальной папке .git/
внутри папки проекта.
Индекс – файл, в котором содержатся изменения, подготовленные для добавления в коммит. Вы можете добавлять и убирать файлы из индекса.
Коммит – фиксация изменений, внесенных в индекс. Другими словами, коммит – это единица изменений в вашем проекте. Коммит хранит измененные файлы, имя автора коммита и время, в которое был сделан коммит. Кроме того, каждый коммит имеет уникальный идентификатор, который позволяет в любое время к нему откатиться.
Указатели HEAD
, ORIG_HEAD
и т. д. – это ссылка на определенный коммит. Ссылка – это некоторая метка, которую использует Git или сам пользователь, чтобы указать на коммит.
Ветка – это последовательность коммитов. Технически же, ветка – это ссылка на последний коммит в этой ветке. Преимущество веток в их независимости. Вы можете вносить изменения в файлы на одной ветке, например, пробовать новую функцию, и они никак не скажутся на файлах в другой ветке. Изначально в репозитории одна ветка, но позже мы рассмотрим, как создавать другие.
Рабочая копия – Директория .git/
с её содержимым относится к Git. Все остальные файлы называются рабочей копией и принадлежат пользователю.
Настройки Git
В зависимости от области действия и места хранения в Git существуют 3 типа настроек:
- Системные. Представляют собой настройки на уровне всей системы, то есть они распространяются на всех пользователей. Файл с этими настройками хранится по следующему пути:
C:\Program Files\Git\etc\gitconfig
для Windows и/etc/gitconfig
для пользователей Linux/MacOS. - Глобальные. Эти настройки одинаковы для всех репозиториев, созданных под вашим пользователем. Среди них есть, например, имя ветки по умолчанию. Файл с этими параметрами хранятся по следующему адресу:
C:/User/<имя пользователя>/.gitconfig
в windows, или~/.gitconfig
в Unix системах. - Локальные. Это настройки на уровне репозитория, они не будут применяться к другим вашим проектам. Эти параметры хранятся в каждом вашем репозитории по адресу:
.git/config
.
Области действия настроек Git (источник: smartiqa.ru/courses/git):
Изменить настройки Git можно двумя способами:
- Отредактировать файл
gitconfig
(на уровне системы) или.gitconfig
(глобально) или.git/config
(на уровне репозитория) напрямую, то есть используя текстовый редактор. - Воспользоваться утилитой
git config
. Кроме того, с помощью этой утилиты можно посмотреть значение соответствующего параметра.
Команда
git config
устанавливает значение соответствующего параметра в конфигурации Git.Документация здесь.
Давайте попробуем задать имя пользователя глобально. Воспользуемся утилитой git config
с параметром --global
:
git config --global user.name "DevOps Student"
git config --global user.email devops@example.com
Посмотреть заданные переменные можно:
git config --global user.name
git config --global user.email
Файл $HOME/.gitconfig
с заданным пользователем:
[user]
name = DevOps Student
email = devops@example.com
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
Как видно поля user.name
и user.email
действительно стали такими, какими мы их задали.
Команда
git config --list --show-origin
показывает все заданные переменные списком (--list
) и откуда они наследованы (--show-origin
).
Создание репозитория
Как было сказано выше, репозиторий должен обязательно содержать папку .git/
с историей этого репозитория. Создать эту папку можно двумя способами:
- Создать новый репозиторий.
- Клонировать к себе на компьютер существующий репозиторий.
Второй способ мы рассмотрим позже, а пока займемся первым. Итак, чтобы создать репозиторий, вам понадобится команда git init
.
Команда
git init
создает пустой репозиторий в директории, откуда была вызвана.Документация здесь.
Создадим папку devops
и на ее базе создадим репозиторий Git:
mkdir devops
cd devops/
git init
Эта команда создала папку .git
внутри папки вашего проекта. В ней следующее содержимое:
devops/.git
├── HEAD
├── branches
├── config
├── description
├── hooks
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
Подробнее о том, что содержится в этой папке и как оно изменяется вы можете изучить в курсе smartiqa.ru/courses/git и в учебнике git-scm.com/book.
Состояния файлов
Давайте более подробно разберемся с тем, в каких состояниях могут быть файлы с точки зрения Git. Каждый файл может находится только в одном из двух состояний:
- Отслеживаемым (tracked). Об этих файлах Git знает и отслеживает изменения в них. Отслеживаемые файлы в свою очередь могут находится в следующих состояниях:
- Неизмененным (unmodified). То есть с момента последнего коммита в файле не было никаких изменений
- Измененным (modified). То есть с последнего коммита в файле были произведены какие-то изменения.
- Подготовленным к коммиту (staged). Это значит, что вы внесли изменения в этот файл и затем проиндексировали их, и эти изменения будут добавлены в следующий коммит.
- Неотслеживаемым (untracked). О неотслеживаемых файлах Git не знает, поэтому изменения в них не будут добавлены в коммит. Это любые файлы в вашем рабочем каталоге, которые не входили в последний коммит и не подготовлены к текущему коммиту.
Наглядная визуализация состояний и переходов между ними (источник: git-scm.com/book):
Чтобы посмотреть статус текущих файлов, нам потребуется команда git status
.
Команда
git status
выводит информацию о статусе файлов, находящихся в репозитории.Документация здесь.
Предположим, вы добавили в свой проект новый файл, простой файл README.
echo 'My Project' > README
Наша папка будет выглядеть следующим образом:
devops/
└── README
Если этого файла раньше не было, и вы выполните git status
, вы увидите свой неотслеживаемый файл вот так:
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
Видно, что на данный момент у нас нет ни одного коммита.
Отслеживание файлов
Чтобы сделать файл отслеживаемым, существует команда git add
.
Команда
git add
добавляет файлы в индекс.Документация здесь.
Отслеживание новых файлов
Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add
. Чтобы начать отслеживание файла README, вы можете выполнить следующее:
git add README
Если вы снова выполните команду status
, то увидите, что файл README
теперь отслеживаемый и добавлен в индекс:
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
Вы можете видеть, что файл проиндексирован, так как он находится в секции Changes to be committed
. Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add, будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее выполнили git init
, затем вы выполнили git add
(файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль. Команда git add
принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет все файлы из указанного каталога в индекс.
Индексация изменённых файлов
Давайте модифицируем файл, уже находящийся под версионным контролем.
echo 'My Project 2' > README
Если вы измените отслеживаемый файл README и после этого снова выполните команду git status
, то результат будет примерно следующим:
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README
Что за чёрт? Теперь README
отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add
. Если вы выполните коммит сейчас, то файл README
попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add
, а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit
. Если вы изменили файл после выполнения git add
, вам придётся снова выполнить git add
, чтобы проиндексировать последнюю версию файла:
git add README
После этого снова выполните команду git status
, то результат будет примерно следующим:
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
Игнорирование файлов
Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых. К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т. п.). В таком случае, вы можете создать файл .gitignore
. с перечислением шаблонов соответствующих таким файлам. Вот пример файла .gitignore
:
*.[oa]
*~
Первая строка предписывает Git игнорировать любые файлы заканчивающиеся на .o
или .a
— объектные и архивные файлы, которые могут появиться во время сборки кода. Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (~
), которая используется во многих текстовых редакторах, например Microsoft Word
, для обозначения временных файлов.
Коллекцию полезных шаблонов файлов .gitignore
можно найти в репозитории github.com/github/gitignore.
Подробнее о написании регулярных выражений для игнорирования определенных файлов можно найти в учебнике git-scm.com/book и в статье на tproger.ru.
Запись изменений в репозиторий
Команда
git commit
- создает новый коммит с файлами из индекса.Документация здесь.
Основы работы с Git предполагают понимание коммитов. Команда git commit
откроет текстовый редактор для ввода сообщения коммита. Также эта команда принимает несколько аргументов:
-m
позволяет написать сообщение вместе с командой, не открывая редактор. Напримерgit commit -m "Пофиксил баг"
;-a
переносит все отслеживаемые файлы в область подготовленных файлов и включает их в коммит (позволяет пропустить git add перед коммитом);--amend
заменяет последний коммит новым изменённым коммитом, что бывает полезно, если вы неправильно набрали сообщение последнего коммита или забыли включить в него какие-то файлы.
Ловушка
git commit
. По умолчанию командаgit commit
откроетVim
, из которого выход найти сложно 😈.Как выйти из Vim можно найти здесь.
Советы для эффективного введения в Git:
- Коммитьте как можно чаще.
- Одно изменение — один коммит: не помещайте все не связанные между собой изменения в один коммит, разделите их, чтобы было проще откатиться.
- Формат сообщений: заголовок должен быть в повелительном наклонении, меньше 50 символов в длину и должен логически дополнять фразу
this commit will ___
(this commit will fix bugs
— этот коммит исправит баги). - Сообщение должно пояснять, почему был сделан коммит, а сам коммит показывает, что изменилось.
- Если у вас много незначительных изменений, хорошим тоном считается делать небольшие коммиты при разработке, а при добавлении в большой репозиторий объединять их в один коммит (про сжатие коммитов читайте здесь).
Запишем изменения для нашего примера:
git commit -m "Добавил README"
Результат:
[main (root-commit) 02c9b2c] Добавил README
1 file changed, 1 insertion(+)
create mode 100644 README
А так выглядит наш коммит GitKraken:
Важно не просто коммитить, но и блюсти формат сообщений.
Хорошая древняя статья на тему того КАК нужно писать сообщения к коммитам тут.
История коммитов
HEAD
– это указатель, задача которого ссылаться на определенный коммит в репозитории.
Команда
git log
показывает журналы фиксации.Документация здесь.
Предположим, что в нашем тестовом репозитории мы 2 раза изменили файл README
и записали изменения. Тогда результат выполнения команды git log --oneline
будет иметь вид:
fbc8910 (HEAD -> main) Исправил замечание
90f038e Добавил описание о HEAD
02c9b2c Добавил README
Эти коммиты создавались в порядке от самого нижнего (02c9b2c
) к самому верхнему (fbc8910
). Каждый раз, когда мы записывали новый коммит в репозиторий, HEAD
смещался и указывал на него.
После того как вы записали коммит с id = fbc8910
, указатель HEAD
стал показывать на него, т.е. данный коммит будет родителем для следующего, и когда мы сделаем еще один коммит, HEAD
сместится.
Более подробно об указателе HEAD
читайте в статье devpractice.ru
Пример истории коммитов (источник: tproger.ru):
Коммиты хранят состояние файловой системы в определённый момент времени и указатели на предыдущие коммиты. Каждый коммит содержит уникальную контрольную сумму — идентификатор, который Git использует, чтобы ссылаться на коммит. Чтобы отслеживать историю, Git хранит указатель HEAD
, который указывает на первый коммит (мы следуем по цепочке коммитов в обратном порядке, чтобы попасть к предыдущим коммитам).
Мы можем ссылаться на коммит либо через его контрольную сумму, либо через его позицию относительно HEAD
, например HEAD~4
ссылается на коммит, который находится 4 коммитами ранее HEAD
.
Более подробную информацию о git log можно найти в статье на tproger.ru.
Удалённый репозиторий
Пока что мы обсуждали использование Git только на локальной машине. Однако мы можем хранить историю коммитов удалённых репозиториев, которую можно отслеживать и обновлять.
Команда
git remote
управляет набором отслеживаемых удаленных репозиториев.Документация здесь.
git remote -v
выводит список удалённых репозиториев, которые мы отслеживаем, и имена, которые мы им присвоили.
Команда
git clone
клонирует репозиторий в новый каталог.Документация здесь.
При использовании команды git clone <url репозитория>
мы не только загружаем себе копию репозитория, но и неявно отслеживаем удалённый сервер, который находится по указанному адресу и которому присваивается имя origin
.
Наиболее употребляемые команды:
git remote add <имя> <url>
— добавляет удалённый репозиторий с заданным именем;git remote remove <имя>
— удаляет удалённый репозиторий с заданным именем;git remote rename <старое имя> <новое имя>
— переименовывает удалённый репозиторий;git remote set-url <имя> <url>
— присваивает репозиторию с именем новый адрес;git remote show <имя>
— показывает информацию о репозитории.
Команда
git fetch
загружает объекты и ссылки из другого репозитория.Документация здесь.
Команда
git pull
- извлечение и интеграция с другим репозиторием или локальной веткой.Документация здесь.
Команда
git push
- обновление удаленных ссылок вместе со связанными объектами.Документация здесь.
Следующие команды работают с удалёнными ветками:
git fetch <имя> <ветка>
— получает данные из ветки заданного репозитория, но не сливает изменения;git pull <имя> <ветка>
— сливает данные из ветки заданного репозитория;git push <имя> <ветка>
— отправляет изменения в ветку заданного репозитория. Если локальная ветка уже отслеживает удалённую, то можно использовать простоgit push
илиgit pull
.
Иллюстрация git push
и git pull
(источник: tproger.ru):
Таким образом несколько людей могут запрашивать изменения с сервера, делать изменения в локальных копиях и затем отправлять их на удалённый сервер, что позволяет взаимодействовать друг с другом в пределах одного репозитория.
Работа с ветками
Ветвление
Ветвление — это возможность работать над разными версиями проекта: вместо одного списка с упорядоченными коммитами история будет расходиться в определённых точках. Каждая ветвь содержит легковесный указатель HEAD на последний коммит, что позволяет без лишних затрат создать много веток. Ветка по умолчанию называется master, но лучше назвать её в соответствии с разрабатываемой в ней функциональностью.
Итак, есть общий указатель HEAD
и HEAD
для каждой ветки. Переключение между ветками предполагает только перемещение HEAD
в HEAD
соответствующей ветки.
Команда
git branch
- получить список, создание или удаление ветвей.Документация здесь.
Команды:
git branch <имя ветки>
— создаёт новую ветку с HEAD
, указывающим на HEAD
. Если не передать аргумент <имя ветки>
, то команда выведет список всех локальных веток;
git checkout <имя ветки>
— переключается на эту ветку. Можно передать опцию -b
, чтобы создать новую ветку перед переключением;
git branch -d <имя ветки>
— удаляет ветку.
Пример выполнения этих команд:
Локальный и удалённый репозитории могут иметь немало ветвей, поэтому когда вы отслеживаете удалённый репозиторий — отслеживается удалённая ветка (git clone
привязывает вашу ветку main
или master
к ветке origin/main
или origin/master
удалённого репозитория).
Привязка к удалённой ветке:
git branch -u <имя удалённого репозитория>/<удалённая ветка>
— привязывает текущую ветку к указанной удалённой ветке;git checkout --track <имя удалённого репозитория>/<удалённая ветка>
— аналог предыдущей команды;git checkout -b <ветка> <имя удалённого репозитория>/<удалённая ветка>
— создаёт новую локальную ветку и начинает отслеживать удалённую;git branch --vv
— показывает локальные и отслеживаемые удалённые ветки;git checkout <удалённая ветка>
— создаёт локальную ветку с таким же именем, как у удалённой, и начинает её отслеживать.
В общем, git checkout
связан с изменением места, на которое указывает HEAD
ветки, что похоже на то, как git reset
перемещает общий HEAD
.
Слияние
Дадим определения:
- Сливаемая ветка – та ветка, с которой мы берем изменения, чтобы влить их в целевую.
- Целевая ветка – та ветка, в которую мы сливаем наши изменения.
- Слияние веток – это перенос изменений с одной ветки на другую. При этом слияние не затрагивает сливаемую ветку, то есть она остается в том же состоянии, что позволяет нам потом продолжить работу с ней.
Слияние включает в себя создание нового коммита, который основан на общем коммите-предке двух ветвей и указывает на оба HEAD
в качестве предыдущих коммитов.
Пример слияния (источник: tproger.ru):
Команда
git merge
сливает изменения с переданной ветки в текущую.Документация здесь.
Для слияния мы переходим на основную ветку и используем команду git merge <тематическая ветка>
.
Если обе ветви меняют одну и ту же часть файла, то возникает конфликт слияния — ситуация, в которой Git не знает, какую версию файла сохранить, поэтому разрешать конфликт нужно собственноручно. Чтобы увидеть конфликтующие файлы, используйте git status
.
Пример с двумя ветками, в которых изменен один и тот же файл:
Переходим в ветку main
через git checkout main
и делаем git merge new-branch
.
Статус репозитория:
git status
показывает:
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README
no changes added to commit (use "git add" and/or "git commit -a")
После открытия таких файлов вы увидите похожие маркеры разрешения конфликта:
Замените в этом блоке всё на версию, которую вы хотите оставить, и подготовьте файл. После разрешения всех конфликтов можно использовать git add
и git commit
для завершения слияния.
Часть 2. Создание репозитория
Вам предстоит работать автономном самоуправляемом экземпляре GitLab (GitLab Self managed).
После регистрации в Gitlab, создайте приватный пустой проект в пространстве имен вашего профиля (Your work/Projects/New project/Create blank project
):
Часть 3. Клонирование репозитория
Созданный удаленно репозиторий необходимо склонировать на рабочую станцию.
Это можно сделать с помощью:
- команды
git clone
в терминале; - через графический интерфейс git (см. пример ниже);
- через Visual Studio Code.
В данном руководстве мы будем делать через графический интерфейс git через токены авторизации.
В повседневной практике рекомендуется работу через SSH с удаленными репозиториями. О том, как это сделать, см. в статье SSH и удалённые git-репозитории.
Нам требуется ссылка, которая указана в разделе "Клонировать с помощью HTTPS".
Ссылку на репозиторий можно узнать непосредственно на страничке созданного вами проекта:
Получение токена
При доступа к приватному репозиторию необходим токен доступа. В данном руководстве используется персональный токен доступа.
Его можно получить в профиле пользователя:
Выпуск токенов находится во вкладке редактирования профиля:
Для создаваемого токена необходимо указать имя, дата истечения и сферы применения (read_repository
и write_repository
):
Клонирование репозитория через GUI
В данной статье используется Sourcetree для наглядности процесса клонирования. Вы можете осуществлять управление локальным репозиторием с помощью любого инструмента с графическим интерфейсом или через команды в терминале.
Интерфейс Sourcetree для macOS и Windows отличается, но подход в работе схож. Для демонстрации используется Sourcetree для Windows.
В интерфейсе выбираем клонирование репозитория по Url:
Вводим данные для авторизации (включая ранее выпущенный токен):
Указываем целевой путь и название:
В результате откроется окно управления репозиторием:
Часть 4. Создание проекта
В данной статье мы создадим наш тестовый проект. Наш проект будет на Python. Для иллюстрации в данном репозитории используется Visual Studio Code. Как использовать Python и Visual Studio Code показано в статье.
При работе над проектом не забудьте использовать изолированную среду Python. С помощью Virtualenv создадим ее в папке проекта:
python3 -m venv env
Если мы создали ее в папке проекта, то не забываем исключить папку со средой из управления системой контроля версий. Для этого в корне репозитория создается файл .gitignore
с необходимым паттерном для игнорирования:
*env
Если вы используете IDE, то не забывайте добавить в игнорируемые служебные объекты. Например, Visual Studio Code:
*env
.vscode
__pycache__
В корне репозитория создадим файл hypotenuse.py
:
import math
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
if __name__ == "__main__":
a = 1
b = 2
print(get_hypotenuse(a,b))
Ошибка в коде допущена специально.
В результате в репозитории получиться следующая структура файлов и папок:
my-awesome-project
├── hypotenuse.py
├── README.md
└── .gitignore
Часть 5. Первая часть изменений
Материал статьи основан на "Laboratory work II"
В этой части работы предлагается:
-
Зафиксировать изменения в репозитории с осмысленным сообщением.
-
Измените исходный код так, чтобы программа через стандартный поток ввода запрашивалось ввод чисел
a
иb
. А в стандартный поток вывода печатались какие-нибудь информационные сообщения. Например:import math
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
if __name__ == "__main__":
print("Введите a:")
a = int(input())
print("Введите b:")
b = int(input())
print("c =", get_hypotenuse(a,b)) -
Зафиксируйте новую версию программы.
-
Отправьте изменения в удалённый репозиторий.
-
Проверьте, что история коммитов доступна в удаленном репозитории.
Часть 6. Вторая часть изменений
Материал статьи основан на "Laboratory work II"
В этой части работы предлагается:
-
В локальной копии репозитория создайте локальную ветку
feature1
. -
Внесите изменения в ветке
feature1
. Например, добавьте расчет площади прямоугольного треугольника. Сделайте в этой функциональности осознанную ошибку. -
Зафиксируйте и отправьте изменения в удалённый репозиторий.
-
Так как мы добавили новую функциональность, то нужно переименовать исходный наш файл в
calculator.py
. -
Зафиксируйте и отправьте изменения в удалённый репозиторий.
По итогу в репозитории должна получиться следующая ситуация:
my-awesome-project
├── calculator.py
├── README.md
└── .gitignoreА код
calculator.py
выглядит следующим образом:import math
def get_area(a, b):
return a * b
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
if __name__ == "__main__":
print("Введите a:")
a = int(input())
print("Введите b:")
b = int(input())
print("c =", get_hypotenuse(a,b))
print("S =", get_area(a,b)) -
Проверьте, что ветка
feature1
доступна в удаленном репозитории. Например, результат может выглядеть так:
Часть 7. Запрос на слияние
Материал статьи основан на "Creating merge requests"
Создание запроса на слияние
Далее нам предстоит создать запрос на слияние. Сделать это можно из списка запросов на слияние в интерфейсе управления удаленным репозиторием. Для этого:
-
Перейдите на главную страницу созданного ранее проекта.
-
В меню слева выберите
Merge requests
: -
В правом верхнем углу выберите
New merge request
. -
Выберите исходную (
feature1
) и целевую (master
) ветви, а затем сравните ветви и продолжите. -
Заполните поля и выберите
Create merge request
.
Запросы на слияние разрабатываются на основе взаимно однозначных
(1:1)
отношений ветвления. Одновременно с заданной целевой веткой может быть связан только один открытый запрос на слияние.
Принятие запроса на слияние
Осуществите проверку запроса на слияние:
В случае отсутствия замечаний и проблем, подтвердите запрос на слияние (Approve
), активируйте флаги Delete source branch
и Squash commits
, и нажмите на Merge
.
Проверьте результат слияния в удаленном репозитории:
Работа с локальным репозиторием
В локальном репозитории выполните следующие шаги:
- Перейдите в ветку master с помощью команды
git checkout
. - Вытяните все изменения в локальном репозитории из удаленного через
git pull
. - С помощью команды
git log
просмотрите историю в локальной версии веткиmaster
. - Удалите локальную ветку
feature1
.
Часть 8. Третья часть изменений
Материал статьи основан на "Laboratory work II"
В этой части работы предлагается:
-
Создать новую локальную ветку
patch1
. -
В этой ветке добавить комментарии к коду в файле
calculator.py
. Например, так:import math
# Получить площадь прямоугольного треугольника
def get_area(a, b):
return a * b
# Рассчитать гипотенузу
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
if __name__ == "__main__":
print("Введите a:")
a = int(input())
print("Введите b:")
b = int(input())
print("c =", get_hypotenuse(a, b))
print("S =", get_area(a, b)) -
Зафиксируйте и отправьте изменения в удалённый репозиторий.
-
Перейдите в локальную ветку
master
. В этой ветке измените порядок функцийcalculator.py
. Например, так:import math
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
def get_area(a, b):
return a * b
if __name__ == "__main__":
print("Введите a:")
a = int(input())
print("Введите b:")
b = int(input())
print("c =", get_hypotenuse(a, b))
print("S =", get_area(a, b)) -
Зафиксируйте и отправьте изменения в удалённый репозиторий.
-
Создайте запрос на слияние.
-
Убедитесь в наличии конфликта:
-
Проверьте, просмотрите и объедините локально. Подсказку о том, что делать, можно посмотреть в GitLab, нажав на кнопку
Merge locally
: -
Зафиксируйте и отправьте изменения в удалённый репозиторий.
-
Убедиться, что открытый ранее запрос на слияния осуществлен:
-
Просмотреть текущий граф в удаленном репозитории:
Итоговый файл calculator.py
, который получился для демонстрации:
import math
# Рассчитать гипотенузу
def get_hypotenuse(a, b):
return math.sqrt(math.pow(a, 3) + math.pow(b, 3))
# Получить площадь прямоугольного треугольника
def get_area(a, b):
return a * b
if __name__ == "__main__":
print("Введите a:")
a = int(input())
print("Введите b:")
b = int(input())
print("c =", get_hypotenuse(a, b))
print("S =", get_area(a, b))
Для дальнейшего изучения
Книги
- Фишерман Л. В. Практическое руководство. Управление и контроль версий в разработке программного обеспечения
Курсы
Статьи
- Введение в Git: от установки до основных команд
- Git за полчаса: руководство для начинающих
- Что такое GIT простым языком? Как работает, основные команды GIT