Git push branch z jednego pilota do drugiego?

136

Mam skonfigurowane następujące piloty:

$ git remote 
korg
rorg

Oraz następujące gałęzie:

$ 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

Teraz chcę wypchnąć wszystkie zdalne gałęzie z korgdo rorgzdalnego. Jak mogę to zrobić?

Najlepiej bez tworzenia lokalnego oddziału dla każdego w pierwszej kolejności, jeśli można tego uniknąć.

Bjarke Freund-Hansen
źródło
Zgaduję, że odpowiedź na to pytanie jest porównywalna z odpowiedzią na tę: stackoverflow.com/questions/6922700/… .
Legolas,

Odpowiedzi:

52

Szybki test tworzący tymczasowe repozytoria pokazuje, że możesz zbudować refspec, który może to zrobić:

$ 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

Więc origin / BRANCHNAME: refs / heads / BRANCHNAME

Sprawdzanie w moim rorgpilocie:

pat@host /tmp/rorg (BARE:master)
$ git graph --all
* 5750bca (HEAD, master) c
| * 13fd55a (one) b
|/
* 822e0de a
patthoyts
źródło
5
Dlaczego nie git push rorg origin/one:one(bez refs/heads/) zamiast tego?
Ali
2
@exalted, ponieważ z refs/heads/prefiksem pchasz zdalne rozgałęzienie, które nie musi być wyewidencjonowane doone
ДМИТРИЙ МАЛИКОВ
@patthoyts Wypróbowałem wspomniane polecenie, które mówi, że wszystko jest aktualne, ale mam 10 oddziałów w odległym A i 6 oddziałów w odległym B, więc czy możesz mi powiedzieć, jak mogę przenieść pominięte gałęzie?
Keshav1234
221

Znalazłem ten:

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

I wypchnął wszystkie moje zdalne oddziały z korg do rorg (nawet bez lokalnych kopii oddziałów). Zobacz dane wyjściowe poniżej:

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

A potem możesz zrobić ten sam nacisk na tagsreferencje:

git push rorg 'refs/tags/*:refs/tags/*'
radistao
źródło
2
W wystarczająco nowej (jakiej wersji?) Gita powinna to być akceptowana odpowiedź. @ bjarke-freund-hansen czy chciałbyś zmienić zaakceptowaną odpowiedź, jeśli zgadzasz się na korzyść przyszłych wyszukiwarek?
Jonah Graham
1
„W wystarczająco nowej (jakiej wersji?) Wersji git, powinna to być akceptowana odpowiedź”, jak wiem, powinno to działać dla każdej publicznej wersji gita, ponieważ te symbole wieloznaczne podpisów push i referencji są powszechne
radistao
3
Daje mi Everything up-to-dategit 2.10.0 i nic się nie dzieje, podczas gdy robienie tego samego na poszczególnych gałęziach działa.
user239558
6
Pomyślałem, że powinienem to wywołać: ta metoda wydaje się tworzyć rzeczywistą gałąź na zdalnym wywołaniu HEAD. Ale to można usunąć. git push rorg :HEAD
Mark Stickley
1
Ktoś nie zna struktury piśmiennictwa i zastanawiasz się, jak popchnąć tagi, chcesz tego polecenia: git push rorg refs/tags/*:refs/tags/*. To jest to samo co git push rorg --tags, ale dobrze jest zrozumieć, co te rzeczy robią :)
Mark Stickley
13

Aby uzupełnić odpowiedź patthoyta , oto krótki skrypt powłoki, który przesuwa wszystkie gałęzie z jednego pilota do drugiego:

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

Podsumowując, dla każdej zdalnej gałęzi na zdalnym źródle (z wyłączeniem gałęzi „wskaźnikowych”, takich jak HEAD), wypchnij to odniesienie do zdalnego pilota docelowego. ( ${a//$SRC_REMOTE\/}Bit usuwa zdalną nazwę źródła z nazwy gałęzi, tj . origin/masterStaje się master.)

blahdiblah
źródło
3
dla tych z nas, którzy muszą to zrobić za jednym naciśnięciem: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
6

Działa to w Zsh

Zauważ, że pojedynczy cudzysłów jest niezbędny, aby zapobiec nieoczekiwanej ekspansji parametrów w niektórych przypadkach.

git push rorg 'refs/remotes/korg/*:refs/heads/*'
zhudongfang
źródło
Przepraszam, że nie zgadzam się, ale Twoja odpowiedź jest identyczna z powyższą radistao ( stackoverflow.com/a/21133502/235878 ), która została opublikowana w '14.
Patrick
@Patrick, brakuje Ci kontekstu - i bardzo ważnego, IMO - że odpowiedź , o której wspomniałeś, rzeczywiście została napisana w 2014 roku, ale brakowało pojedynczych cudzysłowów aż do edycji około 1 roku przed Twoim komentarzem. Tak więc w czasie, gdy pisano tę odpowiedź, w rzeczywistości była ona inna w dość istotny sposób.
0xC0000022L
1
@ 0xC0000022L Dziękuję za zwrócenie mi na to uwagi. Widzę, jak rozszerzenie parametrów może przypadkowo wpłynąć na wynik. Moim zdaniem jednak, jeśli ta odpowiedź miałaby podkreślić brakujący pojedynczy cytat, lepiej byłoby to wyraźnie powiedzieć, niż pozostawić czytelnikom pracę detektywa ... w każdym razie myślę, że sprawiedliwe jest przywrócenie głosowanie negatywne, ponieważ jest to rzeczywiście lepsza odpowiedź w '17.
Patrick
@Patrick bardzo prawdziwe, można było wskazać ... a raczej powinno.
0xC0000022L
-1

Dla każdego skryptu, który sugeruję, abyś uruchomił, dobrze byłoby ukryć lub zatwierdzić wszystkie zmiany.

Musiałem przesunąć kilka gałęzi z jednego pilota do drugiego. Te odpowiedzi wymagały wcześniejszego istnienia lokalnych oddziałów

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

Po prostu zmień origin1 na pilota źródłowego, a origin2 na pilota docelowego. Skopiuj to do „remoteBranchCloner.sh” i wywołaj za pomocą „sh callBranchCloner.sh”.

Może być lepszy sposób, ale to nie wystarczy powoduje kilku pchnięć.

Jeśli używasz mojego kodu, prawdopodobnie chcesz użyć buforowania poświadczeń, przeciwnym razie będziesz musiał wpisywać swoje poświadczenia kilka razy.

Dla Windowsa :

Uwaga: ten skrypt jest przeznaczony dla systemu Linux . Jeśli uruchomisz go w "git bash", skrypt zadziała, ale nie możesz go uruchomić z natywnej konsoli bez zainstalowania czegoś specjalnego.

git config [--global] credential.helper wincred

W przypadku systemu Linux

git config [--global] credential.helper cache

Gdzie [--global] oznacza opcjonalne dodanie --global

Jeśli chcesz ustawić zdalne śledzenie dla wszystkich oddziałów na nowego pilota:

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

Przechowywany jako plik .sh i uruchamiany z „sh nazwa_pliku.sh” ustawia wszystkie nadrzędne strumienie na śledzenie zdalnego „nazwy zdalnego”

csga5000
źródło
-1

Ze względu na utworzenie dodatkowej HEADgałęzi w poprzedniej odpowiedzi najczystszym sposobem, jaki znalazłem, jest sklonowanie do czystego repozytorium, a następnie wypchnięcie wszystkich gałęzi do pilota w następujący sposób:

git clone --bare <from-repository>
cd <from-repo-dir>
git push --set-upstream <to-repository> --all
git push --set-upstream <to-repository> --tags
Kurt Vangraefschepe
źródło