Процесс синхронизации веток между git remotes - PullRequest
0 голосов
/ 03 июля 2018

Я работаю над собственной копией git-репозитория buildroot. Я создал копию репо на бесплатном сервере Bitbucket. Я пытаюсь периодически синхронизировать мое частное репо из основного репозитория buildroot.

Я вытащил локальную копию на свой компьютер, используя

git clone https://my_user@bitbucket.org/my_user/buildroot.git

Затем я добавил основной репозиторий buildroot как удаленный

git remote add mainline https://git.buildroot.net/buildroot

git remote -v теперь выглядит так

mainline    https://git.buildroot.net/buildroot (fetch)
mainline    https://git.buildroot.net/buildroot (push)
origin      https://my_user@bitbucket.org/my_user/buildroot.git (fetch)
origin      https://my_user@bitbucket.org/my_user/buildroot.git (push)

Я могу получить изменения из одной ветви (например, master) на пульте mainline, и эти изменения отображаются в моем репозитории origin после git push

get pull mainline master
git push

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

Как видно ниже, в моем личном репо отсутствуют ветви 2018.02.x и 2018.05.x

git branch -a

* master
remotes/mainline/2017.02.x
remotes/mainline/2017.05.x
remotes/mainline/2017.08.x
remotes/mainline/2017.11.x
remotes/mainline/2018.02.x
remotes/mainline/2018.05.x
remotes/mainline/master
remotes/mainline/next
remotes/origin/2017.02.x
remotes/origin/2017.05.x
remotes/origin/2017.08.x

1 Ответ

0 голосов
/ 04 июля 2018

TL; DR

Должен ли я явно ... нажать origin

Да, но не совсем так, как вы думаете. Тем не менее, это может быть наиболее удобным.

Long

Каждый репозиторий Git является независимой сущностью. Remotes (как в вашем собственном репозитории) или разветвления (как в GitHub или Bitbucket fork) записывают идентичность другого Git-репозитория, но эти два репозитория остаются отдельными объектами. Таким образом, у каждого есть свои собственные ветви, не используемые совместно с любым другим репозиторием Git.

То, что является общим для других репозиториев Git, но только в «время совместного использования» (git fetch и git push) являются коммитами . Они передаются с использованием их необработанных хэш-идентификаторов. Это также то, где имена веток действительно входят в рисунок, потому что репозиторий Git находит его коммиты по его именам веток (и другим ссылкам, но здесь мы сконцентрируемся только на именах ветвей).

Помните, что роль имени ветки в репозитории Git состоит в том, чтобы содержать хэш-идентификатор последнего коммита, который должен рассматриваться "в" этой ветке, т. Е. tip commit филиала. Когда вы используете git checkout <em>branch</em>, за которым следует возможный git commit, ваш Git:

  • строит новый коммит
  • при настройке родительского хеш-идентификатора нового коммита для хеш-идентификатора текущего коммита
  • затем записывает новый идентификатор хеша коммита в текущее имя

, чтобы имя ветки снова указывало на последний коммит. Этот коммит наконечника указывает назад на предыдущий совет, который указывает назад на другой предыдущий коммит и т. Д.

Следовательно, git push делает:

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

(Расширение такой ветви - это ускоренная перемотка вперед .)

Если новый коммит (ы) не просто расширяет некоторые существующие ветки (и), эти конкретные обновления имени (ей) должны быть "принудительными": другой Git просто скажет "нет" те запросы на обновление, которые не являются операциями ускоренной пересылки и не являются принудительными.

Однако не требуется, чтобы эти изменения значения имени ветви соответствовали любым фактическим именам ветви в вашем собственном репозитории. Например, рассмотрим распространенный (по крайней мере для меня) случай, когда я работаю над какой-то функцией, и я пишу полдюжины или более коммитов. Исходя из этого, я определил, что определенно определенно хорошая идея, поэтому я запускаю git rebase -i feature и ставлю эту задачу впереди. Тогда я могу запустить:

git push origin <hash>:for-review

и сделайте запрос на выборку на основе for-review. Наглядно то, что у меня есть в моем собственном хранилище на данный момент, выглядит так:

...--o--o   <-- origin/feature
         \
          *   <-- origin/for-review
           \
            o--o--o--o--o   <-- feature

Пять из шести коммитов остаются невыполненными; только один, помеченный * здесь, был добавлен к имени for-review в хранилище в origin. Тем не менее я могу продолжать работать в своем собственном репозитории на своей ветке feature, которая на шесть коммитов опережает origin/feature и на пять комитетов опережает origin/for-review. Мне просто нужно быть осторожным, чтобы помнить, что коммит * теперь используется совместно (что достаточно просто: у него есть имя origin/, которое может его достичь).

Это подводит нас к тому, что вы должны сделать в своем собственном репозитории, чтобы перенести коммиты из репозитория Git на mainline в репозиторий на origin. Сначала вы должны получить коммиты (и их имена, указывающие на подсказки) от mainline:

git fetch mainline

Теперь у вас есть все коммитов ; теперь вы можете обновить origin используя, например ::

git push origin mainline/2018.05.x:2018.05.x

, который будет отправлять любые коммиты, которые origin не имеет, но нуждается в этом, чтобы выполнить эту работу, с последующим созданием имени 2018.05.x для origin, указывающего на тот же коммит, что и ваш mainline/2018.05.x.

По общему признанию, все это немного грязно, но дело в том, что вам не нужно иметь имя ветви для коммитов, если у вас есть некоторое имя от который вы (и ваш Git) можете найти в своем собственном хранилище. Чтобы отправить эти коммиты на другой Git, вы можете git push их по идентификатору хэша или origin/whatever имени, или вы можете создать имя ветки, или делать все что угодно как Пока он определяет соответствующий наконечник коммит. Однако в правой части пары имен lhs:rhs вы должны указать имя, с которым Git на origin будет в порядке при создании или обновлении.

Удобство

С git push (но не git fetch!), Если вы запустите:

git push origin abc

, что "означает" то же самое, что и:

git push origin abc:abc

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

...