Переключение на запрос pull с помощью команды git fetch: новый уровень мастерства

Сегодня для исправления проекта достаточно создать форк (полную удаленную копию проекта, с которой можно работать как угодно), для чего нужно просто выбрать файл, который требуется изменить, нажать Edit (Правка) и сделать коммит с исправлениями.

А что, если вы на другой стороне и получаете запрос pull? Проработанный веб-интерфейс функционирует прекрасно, и зачастую этого вполне достаточно. Нажмите Approve (Подтвердить), затем Merge (Объединить), и готово.

Однако так бывает не всегда. Часто требуется загрузить изменения из запроса pull в локальный репозиторий, протестировать их и посмотреть, как они выглядят в вашей IDE, чтобы разобраться в сути.

Загрузить запрос pull от коллеги или участника проекта с помощью команд fetch и checkout совсем не сложно, однако можно сделать эту процедуру еще проще, если учесть несколько важных нюансов.

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

Перед началом: добавление имени и статуса ветки в приглашение оболочки

Меня поражает, что многие работают с пустым приглашением командной строки, где не отображается ни имя текущей ветки git, ни наличие измененных/неотправленных файлов в рабочем каталоге. Узнали в этом описании себя? Позвольте помочь вам, а заодно поразить ваше воображение!

Сделайте себе одолжение: установите что-нибудь вроде дивного скрипта liquid prompt, который выдает полезные пояснения о состоянии рабочего каталога git (а также других систем контроля версий):

(На скриншоте выше можно увидеть мое приглашение, которое показывает, что я нахожусь в ветке newbranch и добавил 5 строк в файлы, которые отслеживаю в своем рабочем каталоге, а удалил 0 строк.)

Когда все работают в одном репозитории

Если вы всей командой работаете в одном репозитории, переключиться на запрос pull очень просто: достаточно выполнить команды fetch и checkout для ветки, из которой его создавали:

  • Получите все ветки, опубликованные в общем репозитории:

git fetch origin
  • Создайте локальную ветку, которая отслеживает нужную удаленную ветку:

git checkout -b PRJ-1234 origin/PRJ-1234
  • Теперь можно выполнить команды diff и merge, а затем проверять код хоть до потери пульса:

git diff main ./run-tests.sh
  • Когда вы будете довольны результатами, можно просто вернуться в веб-интерфейс и оставить отзыв или сразу нажать Approve (Подтвердить).

Когда участники работают в своих форках

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

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

git remote add jsmith http://bitbucket.org/jsmith/coolproject.git
  • Сначала соберите все последние обновления из origin — основного репозитория:

git checkout main git fetch origin git merge main
  • Получите все ветки, опубликованные в форке участника:

git fetch jsmith
  • Создайте локальную ветку, которая отслеживает нужную удаленную ветку:

git checkout -b jsmith-PRJ-1234 jsmith/PRJ-1234
  • Теперь можно выполнить команды diff и merge, а затем проверять код хоть до потери пульса:

git diff main ./run-tests.sh

Избавление от лишней работы с помощью ссылок на запрос pull

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

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

  • Что делать, если у вас вообще нет доступа к некоторым форкам и переключиться на ветку с исходным кодом невозможно?

Обе эти проблемы можно решить с помощью ссылок на запросы pull, которые предоставляют некоторые серверы git. Я покажу процедуру, которую поддерживают некоторые серверы git и которая немного различается в зависимости от того, какой сервер вы используете. Далее я расскажу, как получить все запросы pull с помощью команды fetch в Stash (данное решение теперь называется Bitbucket Data Center) и GitHub.

Не бойтесь спецификаций ссылок

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

Например, команда:

git fetch +refs/heads/main:refs/remotes/origin/main

…сопоставит удаленную ветку main в удаленном репозитории origin c локальной origin/main, после чего можно будет написать:

git checkout origin/main

…и по-прежнему обращаться к этой удаленной ветке. С помощью знака плюс (+) в определении мы сообщаем git, что ссылку нужно обновить даже без ускоренного слияния.

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

Итак, если у вас есть удаленный репозиторий origin (или upstream), вот что нужно сделать.

Примечание. Как справедливо отметили несколько разработчиков Stash (ныне Bitbucket Data Center), ссылки, которые я продемонстрирую ниже, считаются недокументированными, частными и могут измениться в любое время.

Загрузка всех запросов pull: Stash

  • Сделайте форк репозитория.

  • Клонируйте форк в локальный репозиторий:

git clone git@stash.atlassian.com:durdn/tis.git
git remote add upstream git@stash.atlassian.com:tpettersen/tis.git
  • Получите последние указатели head от человека, сопровождающего репозиторий upstream

git fetch upstream
  • Добавьте спецификацию ссылок, по которой можно будет сопоставить удаленные запросы pull с локальным пространством имен pr. Это можно сделать с помощью команды config:

git config --add remote.origin.fetch '+refs/pull-requests/*/from:refs/remotes/origin/pr/*'
  • Если заглянуть в .git/config, можно увидеть такие записи fetch:

[remote "upstream"]
    url = git@stash.atlassian.com:docker/libswarm.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
    fetch = +refs/pull-requests/*/from:refs/remotes/upstream/pr/*
  • Теперь все ветки запросов pull легко получить с помощью команды fetch:

$ git fetch upstream

remote: Counting objects: 417, done.
remote: Compressing objects: 100% (274/274), done.
remote: Total 417 (delta 226), reused 277 (delta 128)
Receiving objects: 100% (417/417), 105.28 KiB | 0 bytes/s, done.
Resolving deltas: 100% (226/226), done.

From stash.atlassian.com:docker/libswarm
 * [new ref]         refs/pull-requests/10/from-> upstream/pr/10
 [...]
 * [new ref]         refs/pull-requests/100/from -> upstream/pr/100
 * [new ref]         refs/pull-requests/101/from -> upstream/pr/101
 [...]
 * [new ref]         refs/pull-requests/109/from -> upstream/pr/109
 * [new ref]         refs/pull-requests/110/from -> upstream/pr/110
 [...]
  • Чтобы переключиться на конкретный запрос pull, теперь достаточно написать:

git checkout pr/102

Загрузка всех запросов pull: GitHub

Если форки или вышестоящие репозитории находятся на GitHub, все работает точно так же, как указано выше, но команду config нужно изменить:

git config --add remote.origin.fetch '+refs/pull//head:refs/remotes/origin/pr/'

После этого для удаленного репозитория в .git/config появится дополнительная конфигурация команды fetch для сопоставления указателей head запросов pull с локальным пространством имен под названием pr:

[remote "upstream"] url = git@github.com:docker/libswarm.git fetch = +refs/heads/*:refs/remotes/upstream/* fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*

Получение одного запроса pull с помощью ссылок

Если вам не нужно настраивать записи fetch в файле .git/config и вы просто хотите быстро получить запрос pull, достаточно одной команды.

  • Переключение на отдельный запрос pull в Stash:

git fetch refs/pull-requests/your-pr-number/from:local-branch-name
  • Переключение на отдельный запрос pull в GitHub:

git fetch refs/pull/your-pr-number/head:local-branch-name

А если вы поймете, что часто используете вышеперечисленные команды, процесс можно упростить, создав псевдоним git:

# For Stash
git config alias.spr '!sh -c "git fetch origin pull-requests/${1}/from:pr/${1}" -'

# For Github
git config alias.gpr '!sh -c "git fetch origin pull/${1}/head:pr/${1}" -'

После настройки псевдонима получить запрос pull можно простой командой (спасибо inuit):

Заключение

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

Рекомендовано для вас

Блог Bitbucket

Образовательные программы DevOps

Подробнее о Git

В этом разделе вы найдете другие руководства и ресурсы по Git.