
Рисунок 36. Кнопка Merge и инструкции по ручному слиянию запроса
Если вы решаете не сливать запрос, то вы можете просто закрыть запрос на слияние, а открывший его участник будет уведомлен.
Если у вас многозапросов слияния и вы не хотите добавлять пачку удаленных репозиториев или постоянно делать однократный “pull”, то у GitHub есть хитрый трюк, позволяющий это делать. Этот трюк очень сложный, но полезный и мы рассмотрим его немного позже в Спецификации ссылок.
Фактически, GitHub представляет ветки запросов слияния как псевдо ветки на сервере. По умолчанию, они не копируются при клонировании, а существуют в замаскированном виде и вы можете легко получить доступ к ним.
В качестве примера мы используем низкоуровневую команду ls-remote (часто упоминается как “plumbing” команда, более подробно о ней будет рассказано в Сантехника и Фарфор). Обычно, эта команда не используется в повседневных Git операциях, но сейчас поможет нам увидеть какие ссылки присутствуют на сервере.
Если выполнить её относительно использованного ранее репозитория “blink”, мы получим список всех веток, тэгов и прочих ссылок в репозитории.
$git ls-remote https://github.com/schacon/blink
10d539600d86723087810ec636870a504f4fee4d HEAD
10d539600d86723087810ec636870a504f4fee4d refs/heads/master
6a83107c62950be9453aac297bb0193fd743cd6e refs/pull/1/head
afe83c2d1a70674c9505cc1d8b7d380d5e076ed3 refs/pull/1/merge
3c8d735ee16296c242be7a9742ebfbc2665adec1 refs/pull/2/head
15c9f4f80973a2758462ab2066b6ad9fe8dcf03d refs/pull/2/merge
a5a7751a33b7e86c5e9bb07b26001bb17d775d1a refs/pull/4/head
31a45fc257e8433c8d8804e3e848cf61c9d3166c refs/pull/4/merge
Аналогично, если вы, находясь в своём репозитории, выполните команду git ls-remote origin или укажете любой другой удаленный репозиторий, то результат будет схожим.
Если репозиторий находится на GitHub и существуют открытые запросы слияния, то эти ссылки будут отображены с префиксами refs/pull/. По сути это ветки, но так как они находятся не в refs/heads/, то они не копируются при клонировании или получении изменений с сервера — процесс получения изменений игнорирует их по умолчанию.
Для каждого запроса слияния существует две ссылки, одна из которых записана в /head и указывает на последний коммит в ветке запроса на слияние. Таким образом, если кто-то открывает запрос на слияние в наш репозиторий из своей ветки bug-fix, которая указывает на коммит a5a775, то в нашемрепозитории не будет ветки bug-fix (так как она находится в форке), при этом у нас появится pull//head, которая указывает на a5a775. Это означает, что мы можем стянуть все ветки запросов слияния одной командой не добавляя набор удаленных репозиториев.
Теперь можно получить ссылки напрямую.
$git fetch origin refs/pull/958/head
From https://github.com/libgit2/libgit2
* branch refs/pull/958/head -> FETCH_HEAD
Эта команда указывает Git: “Подключись к origin репозиторию и скачай ссылку refs/pull/958/head”. Git с радостью слушается и выкачивает всё необходимое для построения указанной ссылки, а так же устанавливает указатель на коммит в .git/FETCH_HEAD. Далее, вы можете слить изменения в нужную ветку при помощи команды git merge FETCH_HEAD, однако сообщение коммита слияния будет выглядеть немного странно. Так же это становится утомительным, если вы просматриваете многозапросов на слияние.
Существует способ получать все запросы слияния и поддерживать их в актуальном состоянии при подключении к удаленному репозиторию. Откройте файл .git/config в текстовом редакторе и обратите внимание на секцию удаленного репозитория origin. Она должна выглядеть как-то так:
[remote "origin"]
url = https://github.com/libgit2/libgit2
fetch = +refs/heads/*:refs/remotes/origin/*
Строка, начинающаяся с fetch =, является спецификацией ссылок (“refspec”). Это способ сопоставить названия в удаленном репозитории и названиями в локальной папке .git. Конкретно эта строка говорит Git: "все объекты удаленного репозитория из refs/heads должны сохраняться локально в refs/remotes/origin". Вы можете изменить это поведение добавив ещё одну строку спецификации:
[remote "origin"]
url = https://github.com/libgit2/libgit2.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
Последняя строка говорит Git: "Все ссылки, похожие на refs/pull/123/head, должны быть сохранены локально как refs/remotes/origin/pr/123". Теперь, если сохранить файл и выполнить команду git fetch, вы получите:
$git fetch
#…
* [new ref] refs/pull/1/head -> origin/pr/1
* [new ref] refs/pull/2/head -> origin/pr/2
* [new ref] refs/pull/4/head -> origin/pr/4
#…
Все запросы слияния из удаленного репозитория представлены в локальном репозитории как ветки слежения; они только для чтения и обновляются каждый раз при выполнении git fetch. Таким образом, локальное тестирование кода запроса слияния становится очень простым:
Читать дальше