тянуть / толкать из нескольких удаленных мест

743

Коротко: есть ли способ заставить git-репо выдвигать и извлекать из списка удаленных репо (а не один «источник»)?

Длинное: у меня часто бывает ситуация, когда я разрабатываю приложение на нескольких компьютерах с разным подключением - скажем, ноутбук в пути, компьютер «А», когда я нахожусь в определенном месте, и другой компьютер «Б» пока по другому. Кроме того, ноутбук может иметь связь только с «A» или «B», а иногда и с обоими.

Я хотел бы, чтобы git всегда «извлекал» и «давил» на все компьютеры, к которым он в данный момент подключен, чтобы легче было переходить с одной машины на другую и продолжать бесперебойную работу.

Zorzella
источник
39
Примечание для новых посетителей, начиная с 2016 года: правильный в настоящее время способ сделать это, санкционированный первоклассными gitфункциями, включен в ответ Мальвинуса ниже . Принятый ответ неверен.
ELLIOTTCABLE
@Zorzella: Можете ли вы обновить принятый ответ по этому вопросу, это немного сбивает с толку, как это в настоящее время.
ntninja

Ответы:

503

Вы можете настроить несколько удаленных репозиториев с помощью git remoteкоманды:

git remote add alt alt-machine:/path/to/repo

Чтобы получить данные из всех настроенных удаленных устройств и обновить ветви отслеживания, но не объединять их HEAD, выполните:

git remote update

Если в данный момент он не подключен к одному из пультов, он возьмет тайм-аут или выдаст ошибку и перейдет к следующему. Вам придется вручную объединять выбранные репозитории или cherry-pick, в зависимости от того, как вы хотите организовать сбор изменений.

Чтобы получить ветку master из alt и вставить ее в вашу текущую голову, выполните:

git pull alt master

Так что на самом деле git pullэто почти сокращение git pull origin HEAD(на самом деле это выглядит в файле конфигурации, чтобы определить это, но вы поняли идею).

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

araqnid
источник
так что вы говорите, что "git remote add foo ssh: //foo.bar/baz" создает сокращенную форму, но мне все еще нужно зациклить их с помощью "git pull" или зациклить их с помощью "git merge "(какой здесь синтаксис после" git remove update "?) Не будет ли это сокращенное имя работать и для" git push "? Т.е. я не могу "git push foo" и т.д. Спасибо
Zorzella
8
«git pull» - это в основном «git fetch», за которым следует «git merge». «git remote update» просто делает кучу вызовов «git fetch» ​​для вас. Так что остаётся сделать бит "git merge". Вы можете сказать «git merge origin / master», и он слит версию оригинала master в ваш текущий HEAD. «git pull origin master» делает то же самое, хотя сначала он извлекает данные (и, если вы уже сделали удаленное обновление git, больше ничего не нужно извлекать, поэтому он избыточен). Да, вы можете сказать «git push foo», и он отправит все соответствующие ветви на пульт, называемый «foo».
Аракнид
IIUC вы не можете вставить в рабочий репозиторий (в конце концов вы можете выдвигать несовместимые / непроверенные / нежелательные изменения). Мы должны загружаться в пустые репозитории и получать обновления только тогда, когда мы их извлекаем. Таким образом, решение требует рабочего и чистого хранилища на каждой машине?
Joeytwiddle
2
По-видимому, вы также можете сделать одно нажатие на несколько репозиториев, проверьте этот ответ для получения более подробной информации stackoverflow.com/questions/14290113/…
manei_cc
797

Делать это вручную больше не нужно , с современными версиями git! См. Решение Malvineous ниже.

Воспроизводится здесь:

git remote set-url origin --push --add <a remote>
git remote set-url origin --push --add <another remote>

Оригинальный ответ:

Это то, что я использовал в течение долгого времени без плохих последствий и предложено Линусом Торвальдсом в списке рассылки git .

Решение araqnid - это подходящее решение для переноса кода в ваш репозиторий ... но когда у вас, как и у меня, есть несколько эквивалентных авторитетных апстримов (я держу некоторые из моих более важных проектов, клонированных как в частный апстрим, GitHub, так и в Codaset), оно может быть боль подталкивать изменения к каждому, каждый день.

Короче говоря, git remote addвсе ваши пульты индивидуально ... а затем git config -eи добавить объединенный пульт. Предполагая, что у вас есть этот репозиторий config:

[remote "GitHub"]
    url = git@github.com:elliottcable/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/GitHub/*
[branch "Master"]
    remote = GitHub
    merge = refs/heads/Master
[remote "Codaset"]
    url = git@codaset.com:elliottcable/paws-o.git
    fetch = +refs/heads/*:refs/remotes/Codaset/*
[remote "Paws"]
    url = git@github.com:Paws/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/Paws/*

… Чтобы создать объединенный пульт для "Paws"и "Codaset", я могу добавить следующее после всех этих:

[remote "Origin"]
    url = git@github.com:Paws/Paws.o.git
    url = git@codaset.com:elliottcable/paws-o.git

Как только я это сделаю, когда я git push Origin Master, это подтолкнет к обоим Paws/Masterи Codaset/Masterпоследовательно, делая жизнь немного легче.

ELLIOTTCABLE
источник
104
git config -eоткрывает .git/configфайл в выбранном вами редакторе.
Ричард
3
Так, на всякий случай. Подтверждение того, что с 1.7.12.4 все еще выполняется работа с пультом с 2 URL. Спасибо.
Foobar
26
Я назвал «происхождение» удаленным «все», чтобы придать ему немного более чистую семантику
ErichBSchulz
1
@JamesWomack, см. Ответ Мальвинуса ниже. Теперь это «более правильно», так как gitкомандная строка поддерживает это изначально, с git remote set-url ... --add.
ELLIOTTCABLE
1
Под [branch "Master"]набором remote = Originи git pullбудем использовать оба пульта.
Бенгт
264

Начиная с git 1.8 (октябрь 2012 г.) вы можете сделать это из командной строки:

git remote set-url origin --push --add user1@repo1
git remote set-url origin --push --add user2@repo2
git remote -v

Затем git pushнажмите на user1 @ repo1, затем нажмите на user2 @ repo2.

Malvineous
источник
19
Я настоятельно советую против этого решения. Мы использовали его в нашей компании и столкнулись с серьезными проблемами из-за сбоя хуков в одном репозитории, но не в другом. Наборы изменений тогда присутствовали только в одном хранилище.
Михаэль Шмайссер
4
@ MichaelSchmeißer: Предположительно, вы могли видеть сообщения об ошибках при нажатии, исправить проблему, а затем снова нажать, чтобы вернуть все в чистое состояние?
Malvineous
7
Проблема в том, что исправление отклоненного толчка включает изменение коммитов, которые уже были переданы другому репо. Так что, если кто-то уже основывает работу на этих коммитах к тому времени, когда они исправлены, все становится действительно неприятным, как это было в нашем офисе.
Михаэль Шмайссер
9
Ах да, это может быть сложно. Однако мне кажется, что крючки должны быть переработаны. Неудачный толчок не нарушает работу git, поэтому введение новой точки отказа (которая также не позволяет использовать изящную функцию git), вероятно, не лучшее решение. Конечно, я говорю это, не зная, что ваши требования ...
Malvineous
3
Нет. С тех пор, как я написал свой вопрос, я прочитал другие публикации в Интернете, а затем проверил это. Из прочтения других сообщений у меня возникло подозрение, что используется только первая строка. Я только что проверил это: действительно, проверяется только URL из первой строки git fetch. (Учитывая это, я не понимаю, без чего git remote set-url --addможет быть цель --push.)
imz - Иван Захарящев
34

Я добавил эти псевдонимы в мой ~ / .bashrc:

alias pushall='for i in `git remote`; do git push $i; done;'
alias pullall='for i in `git remote`; do git pull $i; done;'
Нона Урбиз
источник
6
Это круто! Я получил псевдоним Git: git config alias.pushall '!for i in git remote; do git push $i; done;'
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
Я думаю, что я предпочитаю решение псевдонима для создания нового пульта. Смотрите также stackoverflow.com/questions/41372919/...
donquixote
1
Небольшой предложенный твик:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Скотт С. Уилсон,
25

Вы можете добавить пульты с помощью:

git remote add a urla
git remote add b urlb

Затем для обновления всех репозиториев сделайте:

git remote update
FelipeC
источник
15

Вот мой пример со скриптом bash внутри .gitconfigраздела псевдонимов

[alias]
        pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"
troex
источник
7

Я добавил два отдельных pushurl для удаленного «источника» в файле .git congfig. Когда я бегу, то git push origin "branchName"он пробежит до каждого URL. Не уверен, что есть более простой способ сделать это, но я работаю над тем, чтобы перейти к исходному коду Github и одновременно к исходному коду My.visualStudio.

[remote "origin"]
  url = "Main Repo URL"
  fetch = +refs/heads/*:refs/remotes/origin/*
  pushurl = "repo1 URL"
  pushurl = "reop2 URl"
dstineback
источник
4

Я позволил себе расширить ответ от nona-urbiz; просто добавьте это в ваш ~ / .bashrc:

git-pullall () { for RMT in $(git remote); do git pull -v $RMT $1; done; }    
alias git-pullall=git-pullall

git-pushall () { for RMT in $(git remote); do git push -v $RMT $1; done; }
alias git-pushall=git-pushall

Применение:

git-pullall master

git-pushall master ## or
git-pushall

Если вы не предоставите какой-либо аргумент ответвления для git-pullall, то извлечение данных с удаленных устройств по умолчанию не будет выполнено; оставил это поведение как есть, так как оно аналогично git.

hsk81
источник
3

Вам понадобится скрипт, чтобы пройти через них. Git не обеспечивает "толкать всех". Теоретически вы можете выполнить push в нескольких потоках, но собственный метод недоступен.

Получить еще сложнее, и я бы рекомендовал делать это линейно.

Я думаю, что ваш лучший ответ - это когда-то иметь машину, на которую все будут толкать / тянуть, если это вообще возможно.

Джефф Ферланд
источник
2
Проблема в том, что, как я описал, нет централизованного всегда доступного окна. Если мне придется написать сценарий зацикливания на bash, пусть будет так, но мне кажется забавным, что распределенный
виртуальный канал
2
Будучи распределенным, он предполагает, что не все доступны или хотят, чтобы их подтолкнули. Это также относится к различным репозиториям, находящимся в разных состояниях, и к предположению, что другие работают над ними одновременно. Порядок отправки и извлечения из набора репозиториев влияет на состояние различных репозиториев, и вам нужно будет сделать несколько проходов, чтобы все они были по-настоящему синхронизированы. Вот почему нет «тянуть / толкать все». Тогда есть конфликты ...;)
Джефф Ферланд
3

Для обновления пультов (т.е. pullдела) все стало проще.

Заявление Линуса

К сожалению, нет даже способа подделать это с помощью git alias.

в ссылочной записи в списке рассылки Git в elliottcable ответ больше не верен.

git fetch узнал --all параметр где-то в прошлом, позволяющий получить все пульты за один раз.

Если не все запрошены, можно использовать --multipleкоммутатор для указания нескольких пультов или группы.

Экес
источник
3

Я хотел работать в VSO / TFS, а затем публично нажать на GitHub, когда будет готов. Начальный репо создан в частном ВСО. Когда пришло время добавлять в GitHub, я сделал:

git remote add mygithubrepo https://github.com/jhealy/kinect2.git
git push -f mygithubrepo master

Работал как чемпион ...

Для проверки работоспособности введите «git remote -v», чтобы получить список репозиториев, связанных с проектом.

C:\dev\kinect\vso-repo-k2work\FaceNSkinWPF>git remote -v
githubrepo      https://github.com/jhealy/kinect2.git (fetch)
githubrepo      https://github.com/jhealy/kinect2.git (push)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (fetch)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (push)

Простой способ, работал для меня ... Надеюсь, это кому-то поможет.

Джо Хили
источник
4
Бездействие git push -fбез причины, например, неудача git pushили точное знание того, что вы делаете, - плохая идея, потенциально вредная. Это также не отвечает на вопрос, но как добавить второй пульт.
Карл Рихтер
2

Добавьте псевдоним для глобального gitconfig (/home/user/.gitconfig) с помощью команды ниже.

git config --global alias.pushall '!f(){ for var in $(git remote show); do echo "pushing to $var"; git push $var; done; }; f'

Как только вы передадите код, мы скажем

мерзавец

подтолкнуть к происхождению по умолчанию. После псевдонима, мы можем сказать,

мерзкий толчок

и код будет обновлен для всех пультов, включая исходный пульт.

dhirajforyou
источник
1

Добавление allпульта становится немного утомительным, так как вам нужно настроить на каждой машине, которую вы используете.

Кроме того, все псевдонимыbash и git псевдонимы предполагают, что у вас есть push для всех пультов. (Пример: у меня есть форк, sshagкоторый я поддерживаю на GitHub и GitLab. У меня есть удаленный апстрим , но у меня нет разрешения на него.)

Вот git псевдоним, который отправляет только на удаленные устройства с включенным URL-адресом @.

psall    = "!f() { \
    for R in $(git remote -v | awk '/@.*push/ { print $1 }'); do \
    git push $R $1; \
    done \
    }; f"
go2null
источник
-3

Добавление нового пульта

git remote add upstream https://github.com/example-org/example-repo.git

git remote -vv

Получить форму из нескольких мест

git fetch --all

Толчок к локациям

git push -u upstream/dev
Дадасо Занзане
источник