Как работать с гитом в команде
Перейти к содержимому

Как работать с гитом в команде

  • автор:

Работа в команде с использованием Git¶

Для организации командной работы над проектом может быть использована система контроля версий файлов Git. Использование Git имеет ряд преимуществ перед другими способами организации совместной работы:

сохранение полной истории изменений файлов с возможностью возврата к предыдущим версиям

синхронизация изменений между пользователями и автоматическое слияние изменений

возможность работы с бинарными файлами большого объёма

Git — распределенная система, и каждый разработчик или дизайнер имеет собственный локальный репозиторий (хранилище). Синхронизация между локальными репозиториями может осуществляться через центральное “общее” хранилище, которое можно разместить на специально выделенной для этой цели машине (сервере). К серверу может быть организован доступ по протоколу SSH.

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

Типичный рабочий процесс¶

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

По завершении некоторого логического этапа работы возникает необходимость фиксации изменений (коммит) и/или синхронизации с коллегами.

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

Локальные изменения загружаются в общее хранилище и становятся доступными для коллег.

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

Перед выполнением команд необходимо перейти в репозиторий, например:

Индивидуальные настройки¶

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

Установленные данные будут использоваться в логе изменений.

Проверка статуса¶

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

Проверить статус можно командой:

Результат команды git status , если все коммиты проведены и нет новых файлов:

Возможный результат команды git status , если имеются изменения. Например, файлы apps_dev/firstperson/firstperson.js и doc_src/git_short_manual.rst изменены, и создан новый файл 123.txt :

Перед коммитом¶

Проверка изменений (текстовых файлов)¶

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

Проверить, что изменилось, во всей директории:

или только в определенном файле:

Возможный результат команды git diff для текстового файла:

Восстановление файлов¶

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

Внесенные изменения будут отменены, поэтому эту команду необходимо выполнять с осторожностью.

Посторонние файлы¶

Если файл значится в списке Untracked files (команда git status ), но контроль версий для него не нужен, его следует удалить или переместить за пределы рабочей директории.

Подготовка к коммиту¶

Добавление файлов¶

Если изменения устраивают, добавить нужные измененные и/или новые файлы для коммита:

Снова проверить статус:

Возможный результат команды git status после добавления некоторых файлов командой git add :

Видно, что для коммита добавлены файлы apps_dev/firstperson/firstperson.js и 123.txt , а файл doc_src/git_short_manual.rst остался недобавленным. Для упрощения работы рекомендуется либо добавлять такие файлы для коммита, либо отбрасывать их изменения командой git checkout .

Удаление файлов¶

Некоторые файлы могут быть отмечены как удаленные из Git после выполнения команды git status , например:

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

Если же файл был удален по ошибке, и его необходимо вернуть, нужно использовать команду git checkout .

Коммит¶

Выполнить коммит командой:

Появится окно текстового редактора (например, nano или vim), в котором нужно ввести комментарий к коммиту на английском языке.

Сохранить изменения и выйти из редактора (в nano Ctrl+O, затем Ctrl+X; в vim ZZ, или ESC :wq).

После совершения коммита рекомендуется снова проверить статус. Коммит совершен правильно, если команда git status отображает nothing to commit, working directory clean .

Синхронизация между репозиториями¶

Из удаленного — в локальный¶

После того как все коммиты сделаны, необходимо загрузить изменения из удаленного (“общего”) репозитория в локальный:

Результат команды git pull , если в удаленном репозитории нет изменений:

Результат команды git pull , если в удаленном репозитории были изменения, и синхронизация прошла успешно:

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

Параметр этой команды — в данном случае dbf3877..9f9700c — указывает, между какими именно коммитами просматриваются изменения. Этот параметр удобно выделить в результатах команды git pull и вставить щелчком мыши (средняя кнопка) в консоли в нужном месте.

Также можно просмотреть лог изменений:

Команда git pull не всегда приводит к успешной синхронизации. Результат команды git pull в случае наличия конфликтов:

Порядок действий при возникновении конфликтов описан далее.

Из локального — в удаленный¶

Затем нужно загрузить изменения из локального репозитория в удаленный (“общий”), чтобы локальные изменения стали доступными для коллег.

Результат команды git push , если в удаленном репозитории уже есть все локальные изменения:

Результат команды git push , если синхронизация прошла успешно:

Результат команды git push , если синхронизация не прошла, потому что сначала не была выполнена команда git pull :

Необходимо выполнить команду git pull .

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

Разрешение конфликтов¶

Общие сведения¶

Конфликты синхронизации происходят, если выполнены оба условия

один и тот же файл был изменен как в локальном, так и в удаленном репозитории, и

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

бинарный файл (текстура, blend-файл) независимо изменен двумя участниками разработки

в текстовой файл в одной и той же строке были внесены разные изменения

один участник разработки изменил файл, а другой — переместил его и т.п.

Хотя конфликты синхронизации — нормальное явление, слишком частое их возникновение замедляет работу. Рекомендуется ставить коллег в известность о начале работ с общими бинарными файлами, а также чаще проводить синхронизацию. Необходимо эффективно распределять работу между участниками разработки, чтобы таких общих файлов было как можно меньше. Этого можно добиться, в частности, подключением всех ресурсов сцены (linking) из отдельных blend-файлов в один мастер-файл.

Порядок действий¶

Не рекомендуется производить какие-либо действия с файлами (изменять, удалять), пока репозиторий находится в конфликтном состоянии.

Первое что необходимо сделать — выполнить команду git status .

Список конфликтующих файлов отображен в разделе Unmerged paths .

Дальнейший порядок действий различен для бинарных и текстовых файлов.

Бинарные файлы¶

На данном этапе конфликтующие бинарные файлы находятся в том состоянии, в котором они находились в локальном репозитории до попытки синхронизации. Файлы полностью функциональны (например, открываются графическими редакторами).

В случае конфликта бинарных файлов необходимо выяснить с коллегами или самостоятельно, какую из версий оставить, а какую отбросить. Выбор осуществляется командой git checkout .

Выбрать локальную версию файла (— -ours). Его можно открыть и убедиться в этом.

Выбрать удаленную версию файла (— -theirs). Его можно открыть и убедиться в этом.

https://amdy.su/wp-admin/options-general.php?page=ad-inserter.php#tab-8

Снова выбрать локальную версию файла (— -ours).

В итоге необходимо остановиться на нужной версии файла. При угрозе потери работы можно сохранить отбрасываемую версию файла вне репозитория.

Текстовые файлы¶

На данном этапе в конфликтующие текстовые файлы Git’ом вносятся как локальные, так и удаленные изменения одновременно, в особом формате. Такие текстовые файлы как правило, не работоспособны.

Пример. Один участник разработки изменил имя сцены с “Blue Lizard” на “Green Lizard” в файле приложения и загрузил изменения в центральный репозиторий. Другой участник разработки изменил в той же строке “Blue Lizard” на “Red Lizard”, совершил коммит и выполнил команду git pull . В результате именно на этого участника ложится ответственность по разрешению конфликта. В его файле приложения будут находиться строки:

В случае конфликта текстовых файлов можно поступить следующим образом. Файлы, содержащие исходный код, необходимо отредактировать с учетом или без учета внесенных обеими сторонами изменений. В то же время экспортированные текстовые файлы сцен (заканчивающиеся на .json) проще повторно экспортировать.

Корректирующий коммит¶

После выбора нужных файлов или редактирования изменений, добавить их для коммита:

Возможный результат выполнения git status после добавления конфликтующих файлов для коммита:

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

Конфликты разрешены, изменения из удаленного репозитория успешно применены в локальном репозитории. Теперь изменения в локальном репозитории, — включающие только что разрешенный конфликт, — можно загрузить в удаленный репозиторий командой git push .

Тэги (метки) предназначены для указания на определенный коммит, например, с целью обозначения стабилизированной версии продукта.

Просмотреть список тэгов:

Создать тэг для релиза от 3 июня 2013 г., указывающий на коммит со стабильной версией проекта:

5.2 Распределённый Git — Участие в проекте

Как именно участвовать в проекте — описать сложно, так как существует очень много различных вариаций как это делать. Так как Git очень гибок, люди могут и работают вместе по-разному. Отсюда и проблема описания участия в проекте — все проекты разные. Переменными здесь являются: количество активных участников, выбранный рабочий процесс, права доступа и, возможно, метод организации внесения вклада в проект извне.

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

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

Следующая проблема — это уровень доступа. Рабочий процесс, используемый для участия в проекте, может сильно отличаться в зависимости от того, есть ли у вас доступ на запись или нет. Если у вас нет доступа на запись, то как проект принимает изменения? Существует ли вообще политика принятия изменений? Как много изменений вы вносите за раз? Как часто вы это делаете?

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

Правила создания коммитов

Прежде чем мы начнём рассматривать конкретные варианты использования, давайте вспомним о сообщениях к коммитам. Наличие чётких рекомендаций по созданию коммитов и их соблюдение делают работу с Git и взаимодействие с другими гораздо проще. Проект Git предоставляет документ, в котором содержится ряд полезных советов по созданию коммитов для отправки патчей — вы можете ознакомиться с ними, прочитав файл Documentation/SubmittingPatches , находящийся в исходных кодах Git.

Для начала, вам не следует отправлять ненужные пробелы. Git предоставляет простой способ проверки — перед коммитом выполните команду git diff —check , которая выведет список ненужных пробелов.

Вывод команды `git diff --check`

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

Далее, постарайтесь делать коммит логически разделённого набора изменений. Если возможно, попытайтесь делать ваши изменения легко понятными — не нужно писать код все выходные, работая над пятью разными задачами, а в понедельник отправлять результат как один большой коммит. Даже если вы не делали коммиты на выходных, то в понедельник используйте область подготовленных файлов для того, чтобы разделить проделанную работу по принципу минимум один коммит на задачу, давая полезные комментарии к каждому из них. Если несколько изменений касаются одного файла, используйте git add —patch для частичного добавления файлов в индекс (детально описано в разделе Интерактивное индексирование главы 7). Состояние проекта в конце ветки не зависит от количества сделанных вами коммитов, так как все изменения добавятся в один момент, поэтому постарайтесь облегчить задачу вашим коллегам, когда они будут просматривать ваши изменения.

Такой подход так же облегчает извлечение или отмену отдельных изменений, если это вдруг потребуется в будущем. Раздел Перезапись истории главы 7 описывает ряд полезных трюков Git для переписывания истории изменений и интерактивного индексирования — используйте эти инструменты для создания чистой и понятной истории перед отправкой проделанной работы кому-то ещё.

Последнее, что нужно иметь ввиду — это сообщение коммита. Привычка создавать качественные сообщения к коммитам позволяет упростить использование и взаимодействие посредством Git. Как правило, ваши сообщения должны начинаться кратким однострочным описанием не более 50 символов, затем должна идти пустая строка, после которой следует более детальное описание. Проект Git требует, чтобы детальное описание включало причину внесения изменений и сравнение с текущей реализацией — это хороший пример для подражания. Пишите сообщение коммита в императиве: «Fix bug» а не «Fixed bug» или «Fixes bug». Вот отличный шаблон хорошего сообщения коммита, который мы слегка адаптировали из шаблона, изначально написанного Тимом Поупом:

Вам и вашим разработчикам будет гораздо проще, если все сообщения ваших коммитов будут так выглядеть. В проекте Git все сообщения к коммитам имеют расширенное форматирование — выполните команду git log —no-merges , чтобы увидеть как выглядит хорошо отформатированная история коммитов.

Большинство примеров в этой книге не используют расширенного форматирования сообщений коммитов; вместо этого мы просто используем параметр -m для команды git commit .

Поступайте так как мы говорим сейчас, а не так как делаем мы.

Небольшая команда

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

В такой среде вы можете использовать рабочий процесс, при котором выполняемые действия аналогичны использованию Subversion или другой централизованной системе. Вы всё ещё можете использовать преимущества создания коммитов оффлайн, значительно более простое ветвление и слияние, но процесс будет очень похожим; основное отличие в том, что слияние происходит на стороне клиента, а не на сервере во время коммита. Давайте посмотрим что происходит, когда два разработчика начинают работать вместе и используют общий репозиторий. Первый разработчик Джон клонирует репозиторий, вносит изменения и делает коммит локально. (В последующих примерах сообщения протокола заменены на …​ с целью их немного сократить.)

Второй разработчик Джессика делает то же самое — клонирует репозиторий и делает коммит:

Затем Джессика отправляет изменения на сервер:

В последней строке примера приведена полезная информация, выводимая после каждой операции отправки изменений. Её базовый формат такой <oldref>..<newref> fromref → toref , где oldref — коммит, на который указывала ветка до отправки, newref — новый коммит, на который ветка указывает сейчас, fromref — имя отправленной локальной ветки, toref — имя ветки в удалённом репозитории, в которую были отправлены изменения. Далее вы увидите похожие результаты в выводе команд, поэтому имея общее представление о значении поможет вам лучше понимать различные состояния репозиториев. Дополнительную информацию можно найти в документации к команде git-push.

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

В данном случае изменения Джона отклонены, так как Джессика уже отправила свои. Это особенно важно для понимания если вы привыкли к Subversion, потому что, как вы могли заметить, разработчики не редактировали один и тот же файл. Если Subversion автоматически делает слияние на сервере при условии, что редактировались разные файлы, то в Git вы должны сначала слить изменения локально. Джон должен получить изменения Джессики и слить их локально, прежде чем сможет отправить свои.

Для начала, Джон получает изменения Джессики (слияния изменений пока что не происходит):

В этот момент локальный репозиторий Джона выглядит примерно так:

Расходящаяся история Джона

Теперь Джон может слить полученные изменения Джессики со своей локальной веткой:

Процесс слияния проходит гладко — история коммитов у Джона выглядит примерно так:

Репозиторий Джона после слияния с `origin/master`

Теперь Джон может протестировать новый код, чтобы убедиться в корректной работе объединённых изменений, после чего он может отправить объединённые изменения на сервер:

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

История коммитов у Джона после отправки на `origin` сервер

Тем временем Джессика создала тематическую ветку с названием issue54 и сделала в ней три коммита. Она ещё не получила изменения Джона, поэтому история коммитов у неё выглядит следующим образом:

Тематическая ветка Джессики

Внезапно Джессика узнаёт, что Джон отправил какие-то изменения на сервер и теперь она хочет на них взглянуть; для этого ей следует получить с сервера все новые изменения:

Это приводит к получению изменений, отправленных Джоном в репозиторий. Теперь, история коммитов у Джессики выглядит так:

История коммитов Джессики после получения изменений Джона

Джессика считает, что её тематическая ветка готова, но так же хочет знать какие изменения следует слить со своей работой перед отправкой на сервер. Для прояснения ситуации он выполняет команду git log :

issue54..origin/master — это синтаксис фильтра, который указывает Git отображать только список коммитов, которые существуют в последней ветке (в данном случае origin/master ), но отсутствуют в первой (в данном случае issue54 ). Более детально этот синтаксис рассматривается в разделе Диапазоны коммитов главы 7.

В данном случае, в выводе команды мы видим только один коммит, сделанный Джоном и ещё не слитый Джессикой. Если она сольёт origin/master , то это будет единственный коммит, который изменит локальное состояние.

Теперь, Джессика может слить изменения тематической ветки и изменения Джона ( origin/master ) в свою локальную ветку master , а затем отправить её на сервер.

Для начала (при условии отсутствия изменений в тематической ветке, не включённых в коммит), Джессика переключается на свою ветку master :

Обе ветки origin/master и issue54 являются отслеживаемыми, поэтому порядок слияния не важен. Конечный результат будет идентичным вне зависимости от порядка слияния, однако история коммитов будет немного отличаться. Джессика решает слить ветку issue54 первой:

Проблем не возникает; как можно заметить, это простое перемещение вперед. Теперь Джессика заканчивает процесс локального слияния объединяя полученные ранее изменения Джона, находящиеся в ветке origin/master :

Слияние прошло чисто и теперь история коммитов у Джессики выглядит следующим образом:

История коммитов Джессики после слияния изменений Джона

Теперь Джессика может отправить свою ветку master в origin/master , при условии что Джон больше не отправлял изменений:

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

История коммитов Джессики после отправки на сервер

Это один из самых простых рабочих процессов. В течение некоторого времени вы работаете в тематической ветке, а затем сливаете изменения в ветку master когда всё готово. Чтобы поделиться проделанной работой, вы сливаете её в вашу ветку master , затем получаете и сливаете изменения из ветки origin/master если таковые имеются, и наконец, отправляете все изменения в ветку master на сервере. В общем виде последовательность выглядит так:

Общий вид последовательности событий в рабочем процессе для нескольких разработчиков

Команда с руководителем

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

Предположим, что Джон и Джессика вместе работают над одной функцией (назовём её «featureA»), при этом Джессика и Джози работают над другой («featureB»). В этом случае компания использует тип рабочего процесса с менеджером по интеграции, при котором работа отдельных групп интегрируется определёнными инженерами, а ветка master основного репозитория может быть обновлена только этими инженерами. При таком сценарии вся работа ведётся в отдельных ветках для каждой команды, а затем объединяется интегратором.

Давайте рассмотрим рабочий процесс Джессики, так как она работает над двумя функциями, параллельно сотрудничая с разными разработчиками. Предположим, что репозиторий уже клонирован и она решает работать сначала над функцией featureA . Джессика создаёт новую ветку для этой функции и некоторое время работает над ней:

В данный момент ей необходимо поделиться проделанной работой с Джоном, поэтому Джессика отправляет ветку featureA на сервер. У Джессики нет доступа на запись в ветку master (он есть только у интеграторов), поэтому для совместной работы с Джоном она отправляет изменения в другую ветку:

Джессика отправляет письмо Джону с уведомлением, что внесённые ей изменения уже доступны в ветке featureA . Пока Джессика ждёт ответа от Джона, она решает поработать над другой функцией featureB вместе с Джози. Для начала, Джесика создаёт новую тематическую ветку, базируясь на состоянии ветки master на сервере:

После этого, Джессика делает несколько коммитов в ветке featureB :

Репозиторий Джессики выглядит следующим образом:

Начальное состояние истории коммитов Джессики

Джессика готова отправить свою работу, но получает письмо Джози, что начальная работа уже отправлена на сервер в ветку featureBee . Теперь Джессике нужно слить эти изменения со своими перед отправкой на сервер. Изменения Джози она получает командой git fetch :

Полагая что Джессика находится в ветке featureB , она может слить полученные изменения Джози со своими при помощи команды git merge :

Одна небольшая проблема — ей нужно отправить слитые изменения из локальной ветки featureB в ветку featureBee на сервере. Для этого в команде git push Джессика указывает названия локальной и удалённой веток, разделённых двоеточием:

Это называется спецификация ссылок. В разделе Спецификации ссылок главы 10 приведено более детальное описание спецификаций ссылок Git и различные способы их использования. Так же обратите внимание на флаг -u ; это сокращение для —set-upstream , который настраивает ветки для упрощения отправки и получения изменений в дальнейшем.

После этого, Джессика получает письмо от Джона, в котором он сообщает, что отправил некоторые изменения в ветку featureA и просит их проверить. Джесика выполняет команду git fetch для получения всех новых изменений, включая изменения Джона:

Теперь, она может посмотреть что именно было изменено путём сравнения полученной ветки featureA со своей локальной веткой:

Если Джессику всё устраивает, то она сливает изменения Джона в свою ветку featureA :

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

В результате история коммитов у Джессики выглядит так:

История коммитов Джессики после изменений в тематической ветке

Джессика, Джози и Джон информируют интеграторов, что ветки featureA и featureBee на сервере готовы к слиянию в основную. После того как интеграторы сольют эти ветки в основную, полученные изменения будут содержать коммит слияния, а история коммитов будет иметь вид:

История коммитов Джессики после слияния тематических веток

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

Основная последовательность описанного рабочего процесса управляемой команды

Форк публичного проекта

Участие в публичном проекте сильно отличается. Так как у вас нет доступа обновлять ветки проекта напрямую, то передавать проделанную работу следует другим способом. В первом примере рассматривается участие в публичном проекте посредством форка на Git платформах, где возможно его простое создание. Большинство сайтов Git хостинга поддерживают такую функцию (включая GitHub, BitBucket, repo.or.cz и другие), как и большинство тех, кто сопровождает проекты, ожидают такого же стиля участия. Следующий раздел посвящен проектам, которые предпочитают принимать исправления в виде патчей по электронной почте.

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

Возможно, вы захотите использовать rebase -i , чтобы объединить несколько коммитов в один или переставить их местами, чтобы сопровождающему было легче проверять патч — смотрите раздел Перезапись истории для получения детальной информации об интерактивном перебазировании.

Когда работа в тематической ветке завершена и вы готовы передать изменения исходному проекту, перейдите на страницу исходного проекта и нажмите кнопку «Fork», тем самым создавая доступный для записи форк проекта. Затем нужно добавить URL на созданный проект как второй удалённый репозиторий, в нашем случае с именем myfork :

После этого следует отправить проделанную работу в него. Проще отправить вашу тематическую ветку, в которой велась работа, чем сливать изменения в вашу ветку master и отправлять её. Если ваши изменения будут отклонены или какой-то из коммитов будет применен выборочно (команда cherry-pick более детально рассматривается в разделе Схема с перебазированием и отбором главы 5), то вы не сможете вернуть состояние вашей ветки master . Если менеджер проекта сольёт, перебазирует или выборочно применит ваши изменения, то вы сможете их получить из оригинального репозитория.

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

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

Команда git request-pull принимает в качестве аргументов название базовой ветки, в которую следует влить изменения из вашей тематической ветки, и ссылку на Git репозиторий, из которого следует получать изменения, а результатом будет список всех изменений, которые вы предлагаете внести. Например, если Джессика хочет отправить Джону запрос слияния и она отправила два коммита в тематическую ветку, то ей следует выполнить команду:

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

В проектах, где вы не являетесь сопровождающим, проще держать ветку master в соответствии с origin/master , а работать в тематических ветках — так вам будет проще отменить изменения, если они будут отклонены. Разделение направлений разработки по изолированным веткам облегчит их перебазирование, когда состояние основного репозитория изменится, а ваши коммиты уже не смогут быть чисто применены. Например, если вы собираетесь отправить исправления на другую тему, не продолжайте работать в той же тематической ветке — создайте новую, базируясь на ветке master основного репозитория:

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

История коммитов в начале работы над `featureB`

Предположим, что сопровождающий проекта слил некоторый набор других патчей, а затем пытается применить вашу первую ветку, но она уже не может быть слита без конфликтов. В этом случае вы можете попытаться перебазировать свою ветку относительно origin/master , разрешить конфликты и заново отправить свои изменения:

Эти действия перепишут историю ваших коммитов, которая станет похожа на История коммитов после работы над featureA .

История коммитов после работы над `featureA`

Так как вы перебазировали ветку, то должны указать флаг -f во время отправки на сервер, чтобы переписать историю ветки featureA коммитами, не являющимися её потомками. Альтернативным решением может быть отправка этих исправлений в ветку с другим названием (например, featureAv2 ).

Давайте рассмотрим ещё один возможный сценарий: сопровождающий посмотрел вашу вторую ветку и ему понравилась идея, но он хочет попросить вас изменить некоторые детали. Возможно, вы так же захотите перебазировать эту ветку относительно текущего состояния ветки master . Вы создаёте новую ветку базируясь на текущей origin/master , сбрасываете все изменения в неё, разрешаете возможные конфликты, делаете изменения в реализации и отправляете её как новую ветку:

Опция —squash берет все изменения из указанной ветки, объединяет их и создаёт новый коммит в текущей ветке без создания коммита слияния. Это значит, что новый коммит будет иметь только одного родителя и будет включать все изменения из другой ветки, а так же позволяет внести дополнительные изменения до фактического создания коммита. Опция —no-commit указывает Git не создавать новый коммит автоматически.

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

История коммитов после работы над `featureBv2`

Публичный проект посредством E-Mail

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

Рабочий процесс похож на предыдущий — вы создаёте тематическую ветку для каждого набора патчей, над которыми собираетесь работать. Основное отличие в способе их передачи проекту. Вместо того, чтобы форкнуть проект и отправить в него свои изменения, вы генерируете почтовую версию для каждого набора коммитов с целью отправки её в список рассылки разработчиков:

Сейчас у вас два коммита, которые вы хотите отправить в почтовую рассылку. Используйте команду git format-patch для генерации файлов в формате mbox, которые можно отправить по почте — это обернёт каждый коммит в сообщение e-mail, где первая строка из сообщения коммита будет темой письма, а остальные строки плюс сам патч будут телом письма. Применение патча в формате e-mail, сгенерированного с помощью команды format-patch , сохраняет всю информацию о коммите должным образом.

Команда format-patch выводит список имён файлов патчей, которые она создаёт. Флаг -M указывает Git искать переименования. В итоге файлы выглядят вот так:

Вы можете редактировать эти файлы, добавляя информацию для списка рассылки, но которую вы не хотите видеть в сообщении к коммиту. Если добавить текст между строкой — и началом патча (строка diff —git ), то разработчики увидят его, но применяться он не будет.

Для отправки в список рассылки можно либо вставить файлы в почтовую программу, либо отправить их из командной строки. Вставка текста обычно сопровождается проблемами форматирования, особенно при использовании «умных» клиентов, которые не заботятся о переносе строк и пробелах соответствующим образом. К счастью, Git предоставляет утилиту, которая умеет отправлять корректно отформатированные патчи по протоколу IMAP. Позже мы покажем как отправлять патчи через Gmail, так сложилось что мы знаем этот почтовый агент лучше других; вы можете воспользоваться инструкциями по использованию большого числа почтовых программ в вышеупомянутом файле Documentation/SubmittingPatches из исходных кодов Git.

Для начала, следует настроить раздел imap в файле

/.gitconfig . Каждое отдельное значение можно установить вызовом команды git config , а можно указать вручную сразу в файле, но в итоге файл конфигурации должен выглядеть следующим образом:

Если ваш сервер IMAP не использует SSL, то последние две строки не обязательны, а значение host должно быть imap:// вместо imaps:// . Как только всё сделано, воспользуйтесь командой git imap-send для помещения ваших патчей в папку Drafts на указанном IMAP сервере:

Теперь вы можете перейти в папку Drafts, изменить поле To, указав адрес почтовой рассылки, при необходимости заполнить поле СС, указав адрес сопровождающего или ответственного, и отправить письмо.

Так же вы можете отправить свои патчи используя SMTP сервер. Как и в предыдущем случае, вы можете использовать набор команд git config или создать секцию sendemail в файле

Отправить патчи можно командой git send-email :

Во время выполнения команды, Git выводит много отладочной информации для каждого отправляемого патча, которая выглядит примерно так:

Помощь по конфигурации, дополнительные советы и рекомендации, а так же тестовое окружение для отправки патчей по email доступны здесь git-send-email.io.

Заключение

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *