Git push branch с одного пульта на другой?

133

У меня установлены следующие пульты:

$ git remote 
korg
rorg

И следующие ветки:

$ git branch -a
* (no branch)
  remotes/korg/gingerbread
  remotes/korg/gingerbread-release
  remotes/korg/honeycomb
  remotes/korg/honeycomb-mr1-release
  remotes/korg/master
  remotes/m/android-2.3.3_r1 -> refs/tags/android-2.3.3_r1a
  remotes/m/gingerbread -> korg/gingerbread

Теперь я хочу перенести все удаленные ветки с korgна rorgудаленный. Как я могу это сделать?

Желательно без создания локальной ветки для каждого первого, если этого можно избежать.

Бьярке Фрейнд-Хансен
источник
Я предполагаю, что ответ на этот вопрос сравним с ответом на этот: stackoverflow.com/questions/6922700/… .
Леголас

Ответы:

52

Быстрый тест создания временных репозиториев показывает, что вы можете создать refspec, который может это сделать:

$ git push rorg origin/one:refs/heads/one
Counting objects: 5, done.
Writing objects: 100% (3/3), 240 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/rorg
 * [new branch]      origin/one -> one

Итак происхождение / ФИЛИАЛ: refs / главы / ФИЛИАЛ

Проверяю свой rorgпульт:

pat@host /tmp/rorg (BARE:master)
$ git graph --all
* 5750bca (HEAD, master) c
| * 13fd55a (one) b
|/
* 822e0de a
patthoyts
источник
5
Почему бы не git push rorg origin/one:one(без refs/heads/) вместо этого?
Али
2
@exalted, потому что с refs/heads/префиксом вы выдвигаете удаленные ветвления, которые не нужно one
регистрировать
@patthoyts Я попробовал указанную команду, в ней все указано в актуальном состоянии, но у меня есть 10 веток на удаленном A и 6 веток на удаленном B, поэтому не могли бы вы рассказать мне, как я могу переместить оставшиеся ветки?
Keshav1234 03
219

Я нашел вот это:

git push rorg 'refs/remotes/korg/*:refs/heads/*'

И он переместил все мои удаленные ветки с korg на rorg (даже без локальных копий веток). См. Вывод ниже:

Counting objects: 293, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (67/67), done.
Writing objects: 100% (176/176), 48.32 KiB, done.
Total 176 (delta 105), reused 168 (delta 97)
remote: Resolving deltas:  11% (12/105)
To <<MY_REPOSITORY_URL>>
 * [new branch]      korg/gingerbread-> gingerbread
 * [new branch]      korg/gingerbread-release -> gingerbread-release
 * [new branch]      korg/honeycomb-> honeycomb
 * [new branch]      korg/HEAD -> HEAD
 * [new branch]      korg/honeycomb-mr1-release-> honeycomb-mr1-release
 * [new branch]      korg/master -> master

И затем вы можете сделать то же самое для tagsссылок:

git push rorg 'refs/tags/*:refs/tags/*'
radistao
источник
2
В достаточно новом (какой версии?) Git этот ответ должен быть принят. @ bjarke-freund-hansen, хотите ли вы изменить принятый ответ, если вы согласны, в интересах будущих поисковиков?
Джона Грэм,
1
«В достаточно новой (какой версии?) Git это должен быть принятый ответ», как я знаю, это должно работать для каждой общедоступной версии git, потому что эти push-подпись и подстановочные знаки ссылок являются обычными
radistao
3
Дает мне Everything up-to-dateна git 2.10.0 ничего не происходит, в то время как делает то же самое на отдельных ветках работает.
user239558
6
Просто подумал, что я должен вызвать это: этот метод, кажется, создает фактическую ветвь на удаленном вызываемом HEAD. Но это можно удалить. git push rorg :HEAD
Марк Стикли
1
Любой не знакомы со структурой и REFS интересно , как раздвинуть теги, Вы хотите эту команду: git push rorg refs/tags/*:refs/tags/*. Это то же самое git push rorg --tags, но хорошо понимать, что делают эти штуки :)
Марк Стикли
14

В дополнение к ответу patthoyt , вот короткий сценарий оболочки, который перемещает все ветви с одного пульта на другой:

SRC_REMOTE=korg
DST_REMOTE=rorg
for a in $(git branch --list --remote "$SRC_REMOTE/*" | grep -v --regexp='->')
  do git push "$DST_REMOTE" "$a:refs/heads/${a//$SRC_REMOTE\/}"
done

Подводя итог, для каждой удаленной ветви на удаленном источнике (исключая ветви-указатели, такие как HEAD), передайте этот ref на удаленный пункт назначения. ( ${a//$SRC_REMOTE\/}Бит удаляет удаленное имя источника из имени ветки, т. Е. origin/masterСтановится master.)

blahdiblah
источник
3
для тех из нас, кому нужно сделать это одним нажатием:git push -u $DST_REMOTE $(for a in $(git branch --list --remote "$SRC_REMOTE/*" | grep -v --regexp='->'); do echo "$a:refs/heads/${a//$SRC_REMOTE\/}"; done)
Jayen
3

Это работает в Zsh

git push rorg 'refs/remotes/korg/*:refs/heads/*'
zhudongfang
источник
Извините, я проголосовал против, но ваш ответ идентичен тому, что указано выше для radistao ( stackoverflow.com/a/21133502/235878 ), который был опубликован в '14.
Патрик
0

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

Мне нужно было перенести несколько веток с одного пульта на другой. Эти ответы требовали, чтобы местные филиалы существовали ранее.

SRC_R=origin1
DEST_R=origin2
for cbranch in $(git branch -r | grep $SRC_R | cut -d '/' -f2,3,4,5 | cut -d ' ' -f1)
do
    git checkout $cbranch
    git push $DEST_R $cbranch
done

Просто измените origin1 на исходный пульт, а origin2 на конечный пульт. Скопируйте это в «remoteBranchCloner.sh» и вызовите его, используя «sh callBranchCloner.sh».

Там может быть лучший способ, который не делает несколько нажатий.

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

Для окон :

Примечание. Этот сценарий предназначен для Linux . Если вы запустите его в «git bash», сценарий будет работать, но вы не сможете запустить его из собственной консоли, не установив что-то особенное.

git config [--global] credential.helper wincred

Для Linux

git config [--global] credential.helper cache

Где [--global] означает необязательное добавление --global

Если вы хотите установить удаленное отслеживание для всех веток на новый пульт:

DEST_R=remotename
for cbranch in `git branch`
do
    git checkout $cbranch
    git branch -u guru/$cbranch
done

Сохранение в виде файла .sh и запуск с "sh filename.sh" установит все восходящие потоки для отслеживания удаленного 'remotename'

csga5000
источник
0

Из-за того, HEADчто в предыдущем ответе была создана дополнительная ветка , самый чистый способ, который я нашел для этого, - это клонировать в чистый репозиторий, а затем отправить все ветки на удаленный компьютер следующим образом:

git clone --bare <from-repository>
cd <from-repo-dir>
git push --set-upstream <to-repository> --all
git push --set-upstream <to-repository> --tags
Курт Ванграфшепе
источник