Как мне настроить промежуточный репозиторий в git?

#git

#git

Вопрос:

Я хочу создать репозиторий [B], который отслеживает мастер удаленного репозитория [A] в ветке с именем x_master. Его собственный мастер также должен быть клоном во время первоначального создания, чтобы другие [разработчики] могли клонировать и вносить изменения.

Иногда, когда в A происходят изменения, мне нужно будет иметь возможность удалять их и объединять в x_master B (что, если я это понимаю, должно быть ускоренной перемоткой вперед, поскольку они будут единственными изменениями в ветке x_master на B), а затем иметь возможность объединятьэти изменения вносятся в мастер B и, следовательно, в любого, кто клонирует мастер B при извлечении.

Что я концептуально хочу, так это:

 master      x_master
 [A] <---------> [B] <-------> [Dev2]
                  ^-------> [Dev1]
                  master
 

В конце концов мне нужно будет перенести изменения в master B на master A, когда все разработки будут выполнены, но в A будут происходить изменения, которые необходимо объединить в B

  • Как мне это настроить?
  • Как мне нажимать и извлекать из B в и из A?
  • Имеет ли смысл эта настройка?

Я перепробовал все виды clone -mirror, branch -track и, похоже, просто не понимаю, как правильно нажимать и извлекать изменения в A и B.

Комментарии:

1. Хорошо, я попытался выяснить, почему вы хотели бы это сделать, но я не понимаю. Почему вы хотите иметь 2 репозитория? В чем разница между ними?

2. 1. Зачем вам нужны два репозитория? Эта линия мышления наряду с другими идеями, которые я видел для использования благословенных репозиториев, являются полной бессмыслицей, когда вы используете git. Если вы хотите иметь промежуточную область, используйте ветку с именем staging . Используйте ветки для всего, что вам нужно разделить.

3. A — это репозиторий, который я не контролирую во внешней системе, не могу вносить изменения, пока мы не завершим нашу разработку, но необходимо объединить изменения.

4. @Mark: Если мой ответ вас не удовлетворяет, пожалуйста, сообщите мне, что вы хотите иметь более подробно.

5. В Bazaar это намного проще.

Ответ №1:

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

 $ cd repo_B
$ git init --bare
$ git remote add upstream URL_FOR_REPO_A
$ git fetch upstream  master:refs/heads/x_master
$ git branch master x_master
 

Когда репозиторий, находящийся выше по потоку, изменен, вам необходимо перенести эти изменения в исходный репозиторий 1:

 $ git fetch upstream  master:refs/heads/x_master
 

Это перезапишет 2 любых возможных изменения x_master , поэтому вам лучше оставить эту ветку в покое. 🙂

Вы захотите объединить изменения в восходящем x_master потоке в master когда / если изменения. К сожалению, на этом этапе могут возникнуть конфликты, поэтому это должно быть сделано с помощью клона нашего простого репозитория. Просто клонируйте репозиторий B (в локальное или удаленное местоположение) и объедините x_master его master , разрешите конфликты и отправьте обратно.

И последняя задача — перенести разработку в master репозиторий A. Это можно сделать двумя способами. Первый — это прямое нажатие мастера B в репозиторий A. Это можно сделать, выполнив:

 $ git push upstream
 

в репозитории B. Альтернативой является более контролируемое слияние с master x_master использованием третьего репозитория:

 $ git clone URL_FOR_REPO_A
$ cd repoDir
$ git remote add dev URL_FOR_REPO_B
$ git fetch dev
$ git branch --track master_b dev/master
$ git merge master_b
$ <resolve conflicts, if any>
$ git push origin master
 

Примечание 1

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

 $ git configure branch.upstream.fetch  master:refs/heads/x_master
 

И с --add его помощью вы даже можете добавить больше ветвей для извлечения:

 $ git configure --add branch.upstream.fetch  branch_1_0:refs/heads/x_branch_1_0
 

Теперь выборка будет работать правильно без ссылок:

 $ git fetch upstream
 

Примечание 2

Чтобы предотвратить отправку в master of repo_B , вы можете использовать перехват на стороне сервера, например pre-receive or update .

Комментарии:

1. ваш первый блок инструкций завершается с ошибкой, когда B пуст, git checkout master потому что нет рабочего каталога. На данный момент я попытался клонировать B, но получил «удаленный заголовок ссылается на несуществующую ссылку». Я считаю, что мне нужно, чтобы B был пустым, потому что люди вкладывают в него.

2. @MarkFisher Упс. Я попробовал это с помощью non-bare и предположил, что простое создание голого репозитория сделает свое дело. Я обновлю ответ для работы с bare.

3. отлично, я смог перенести изменения из A в B: x_master и перейти от devs к B: master, и обнаружил, что могу перенести изменения из B: x_master в A: master, перейдя в B: bare и выполнив git push upstream . Если вы добавите эту последнюю часть к своему ответу, я приму ее (чтобы исключить ее из комментариев). Большое спасибо.

Ответ №2:

Я был вдохновлен, но также несколько смущен ответом валлака. Я думаю, что что-то более простое может работать так же хорошо…

 mkdir (name).staging.git ; cd (name).staging.git
git init --bare
git remote add origin (remote-repo)
 

Периодически (в том числе изначально) вы захотите получать изменения и обновлять локальные ветки…

 git fetch
for remote in $(git branch -r) ; do git branch --force --no-track $(basename $remote) $remote ; done
 

Обратите внимание, что необходимо обновлять локальные ветки каждый раз при извлечении, иначе репозиторий третьего уровня не увидит изменений в восходящем потоке.В моем примере обновляются все локальные ветви, но вместо этого вы можете сделать это вручную только для интересующих ветвей. Я предлагаю создать псевдоним «git staging-fetch», который объединяет эти две строки в одну команду.

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


Примечание: для этой схемы не требуется ветка с именем «x_master». Git имеет встроенную поддержку использования локальной ветки для теневого отображения удаленной ветки. Таким образом, все ветви «master» называются просто «master», но при обращении к ветке в репозитории, находящемся непосредственно в восходящем потоке, вы бы назвали его «origin / master» или «staging / master», в зависимости от обстоятельств.

 branch:       origin master    staging master    working master
              =============    ==============    ==============
origin sees:  master
staging sees: origin/master    master
working sees:                  staging/master    master
 

Комментарии:

1. Примечание: это отличается от простого использования git clone --bare (remote-repo) для создания промежуточного репозитория. При clone --bare этом вы теряете ссылки на удаленные ветви, но, добавив удаленный после установки --bare , вы сохраняете их. Я не знаю, является ли это различие в поведении преднамеренным, но, к счастью, Git предоставляет способ достичь того, что нам здесь нужно.

Ответ №3:

Я предполагаю, что и A, и B — это пустые репозитории, используемые только для нажатия и извлечения, верно?

Я бы сказал, что самым простым способом было бы просто создать промежуточный репозиторий между A и B. То есть не пустой репозиторий с рабочим деревом. Таким образом, вы можете извлекать и объединять из любой ветви в A и B в полном спокойствии и изоляции от всех остальных, настраивать слияния до тех пор, пока они вас полностью не устроят, а затем отправлять их в любую из ветвей A и B.

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

Комментарии:

1. да, оба репозитория пустые. На самом деле, B контролируется Gerrit, поэтому люди будут нажимать на refs/for/master перед слиянием с master, но это на самом деле не имеет значения для проблемы здесь, просто подчеркивает, что она должна быть пустой.

Ответ №4:

Лучшим способом было бы иметь одного ответственного разработчика (назовем его dev0), который будет делать все необходимое. У него должен быть доступ на чтение и запись к A. Он может установить A в качестве удаленного в своем локальном репозитории и поддерживать B /x_master, извлекая коммиты из A/master в свой локальный x_master и передавая его B. Как вы упомянули, это должно быть легко и всегда быстро. (Так что это может быть сценарий)

Поскольку B / x_master также виден всем разработчикам, любой может объединить (и просмотреть / исправить конфликты) x_master с master, когда почувствует необходимость интегрировать его в разработку.

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

Комментарии:

1. разработчики будут запускать (через Gerrit) в master на B. Сложность здесь в том, что нам нужно как можно раньше узнать об изменениях в A, которые могут повлиять на нас, поэтому мне нужно увидеть эти изменения и объединить их в B контролируемым образом, все еще выполняя разработку против нашей основной линии. Я собираюсь создавать экземпляры на основе x_master и master в B каждую ночь, чтобы у нас был контроль качества для обоих, и чтобы мы могли видеть, нарушают ли внешние изменения сборки. Из-за нехватки времени мы не можем позволить изменениям в x_master испортить нашу основную строку, но мы также не можем позволить себе ждать до конца, чтобы объединить их.