#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 испортить нашу основную строку, но мы также не можем позволить себе ждать до конца, чтобы объединить их.