Форки и вышестоящие репозитории в Git: инструкции и интересный совет

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

Вышестоящий репозиторий Git: следите за обновлениями и вносите свой вклад

Сначала ознакомимся с общей конфигурацией и основным рабочим процессом взаимодействия с вышестоящими репозиториями.

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

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

git remote -v

origin  git@bitbucket.org:my-user/some-project.git (fetch)
origin  git@bitbucket.org:my-user/some-project.git (push)

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

git remote add upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git

Убедитесь, что удаленное подключение добавлено правильно:

git remote -v

origin    git@bitbucket.org:my-user/some-project.git (fetch)
origin    git@bitbucket.org:my-user/some-project.git (push)
upstream  git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (fetch)
upstream  git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (push)

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

(Если в проекте есть теги, которые не объединены с главной веткой, нужно также выполнить команду git fetch upstream --tags.)

git fetch upstream

Как правило, нужно, чтобы локальная главная ветка main была точной копией главной ветки mainвышестоящего репозитория, а также чтобы вся работа велась в функциональных ветках, так как впоследствии они могут стать запросами pull.

На этом этапе вы можете свободно выбирать между командами merge и rebase, поскольку в большинстве случаев они дадут одинаковый результат. Воспользуемся командой merge:

git checkout main
git merge upstream/main

Если вы хотите поделиться работой с лицами, ответственными за поддержку вышестоящего репозитория, сделайте ответвление от главной ветки main и создайте функциональную ветку. Когда вы будете удовлетворены результатом, отправьте код в удаленный репозиторий.

Кроме того, вы можете провести перебазирование с помощью команды rebase, а затем выполнить слияние командой merge, чтобы оставить в вышестоящем репозитории чистый набор коммитов (а лучше всего один) для оценки:

git checkout -b feature-x

#some work and some commits happen
#some time passes

git fetch upstream
git rebase upstream/main

Публикация в форке репозитория Git

Выполнив описанные выше действия, опубликуйте работу в своем удаленном форке простой командой push:

git push origin feature-x
git push -f origin feature-x

Я предпочитаю сохранять историю максимально чистой и поэтому выбираю третий вариант, однако у разных команд разные рабочие процессы. Примечание: совершайте эти операции только при работе с собственным форком. НИ В КОЕМ СЛУЧАЕ не перезаписывайте историю общих репозиториев и веток.

Полезный совет: значения опережения/отставания в подсказке

Выполнив команду git status после fetch, вы сможете просмотреть, на сколько коммитов ваша ветка опережает синхронизированную удаленную ветку или отстает от нее. Было бы здорово видеть эту информацию в своей верной командной подсказке, не правда ли? Я тоже так подумал, поэтому настроил в Bash соответствующие параметры.

Вот как будет выглядеть подсказка после настройки:

nick-macbook-air:~/dev/projects/stash[1|94]$

Кроме того, вам понадобится добавить всего одну функцию в .bashrc или аналогичный файл:

function ahead_behind {
    curr_branch=$(git rev-parse --abbrev-ref HEAD);
    curr_remote=$(git config branch.$curr_branch.remote);
    curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
    git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
}
export PS1="\h:\w[\$(ahead_behind)]$"

«Внутренняя кухня»

Изложу принцип работы для тех, кто любит развернутые пояснения.

Получаем символическое имя текущего указателя HEAD, то есть текущей ветки:

curr_branch=$(git rev-parse --abbrev-ref HEAD);

Получаем удаленную ветку, на которую указывает текущая ветка:

curr_remote=$(git config branch.$curr_branch.remote);

Получаем ветку, с которой нужно объединить эту удаленную ветку (в Unix можно легко убрать все символы до последней косой черты [/] включительно):

curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);

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

git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';

Для преобразования символа табуляции в разделитель | используем привычную команду tr в Unix.

Начало работы с вышестоящим репозиторием Git

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

Решение Bitbucket Data Center поддерживает синхронизацию форков, которая освобождает разработчиков от обязанности поддерживать актуальность своих форков. В рамках Bitbucket Cloud используется простая одноэтапная синхронизация. Опробуйте эти возможности самостоятельно!

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

Блог Bitbucket

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

Подробнее о Git

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