Jak mam powiedzieć git-svn o zdalnej gałęzi utworzonej po pobraniu repozytorium?

193

Używam git-svndo pracy z centralnym repozytorium Subversion mojej firmy. Niedawno utworzyliśmy nową gałąź funkcji w centralnym repozytorium.

Jak mam o tym powiedzieć Gitowi? Kiedy uruchamiam, git branch -rwidzę tylko gałęzie, które istniały, gdy działałem fetchprzeciwko repozytorium Subversion, aby zainicjować moje repozytorium Git?

Hank Gay
źródło
Odpowiednie mogą być odpowiedzi: stackoverflow.com/questions/13376917/… .
Tomasz Gandor

Odpowiedzi:

294

Możesz ręcznie dodać zdalną gałąź,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
Vjangus
źródło
3
po prostu dodając ten link do dokumentów jako odniesienie kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
Z .git / config dość łatwo jest zrozumieć, w jaki sposób można skonfigurować zdalne gałęzie z jednego / wielu repozytoriów.
Mikael Lepistö
6
Gdybym mógł to głosować osiem razy, zrobiłbym to. Wreszcie sposób na dodanie gałęzi svn, która jest dodawana w niestandardowej lokalizacji!
Tim Keating
7
Wchodzę fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.na krok kasy.
phpguru
17
@phpguru Spróbuj usunąć flagę opcji -t, aby stała się „git checkout -b local-newbranch newbranch” nie zapomnij dołączyć prefiksu pilota do newbranch (np. origin / newbranch).
mj1531
96

Jeśli chcesz śledzić WSZYSTKIE zdalne gałęzie svn, rozwiązanie jest tak proste, jak:

git svn fetch

Spowoduje to pobranie WSZYSTKICH zdalnych gałęzi, które nie zostały jeszcze pobrane.

Dodatkowa wskazówka: jeśli najpierw sprawdziłeś tylko pień, a później chcesz śledzić WSZYSTKIE gałęzie, edytuj, .git/configaby wyglądać tak i uruchom ponownie git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Kluczowe punkty urlpowinny wskazywać na katalog główny repozytorium, a ścieżki zdefiniowane w fetchi branchespowinny być względne url.

Jeśli chcesz pobrać tylko określone gałęzie zamiast WSZYSTKICH, istnieje ładny przykład w git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

W starszych wersjach git-svn, po określeniu takich gałęzi, możesz nie być w stanie uzyskać nowych gałęzi git svn fetch. Jednym obejściem jest dodanie kolejnych fetchlinii, takich jak to:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Kolejne obejście autorstwa @AndyEstes: edytuj .git/svn/.metadatai zmień wartość branches-maxRevlub tags-maxRevna wersję przed utworzeniem nowo określonych gałęzi lub znaczników. Gdy to zrobisz, uruchom, git svn fetchaby śledzić nową gałąź zdalną svn.

janos
źródło
1
Jeśli już ustawiłeś wersję, do której wykonałeś rozgałęzienie svn przed ustawieniem tych ustawień, możesz chcieć wykonać reset git svn.
kcm1700
3
Edycja .git/svn/.metadatabyła bardzo pomocna! Dodawałem do siebie dodatkowe gałęzie .git/config, które git svn fetchnie odbierały, ponieważ numer wersji metadanych był „zbyt daleko”. W jednym przypadku pobrano tylko ostatnie zatwierdzenie z gałęzi. Ręcznie pozbyłem się wadliwej gałęzi (zmieniłem .git/svn/refs/remotes/svn/qa/XYZjej nazwę .git/svn/refs/remotes/svn/qa/XYZ~, porzuciłem jej istnienie .git/packed-refsitp.) ... wybrałem „wcześniejszą” wersję rewizji dla metadanych… pobiegłem, git svn fetchby w końcu uzyskać pełną historię z poprawnym połączonym wykresem.
starlocke,
8
TO POWINNA BYĆ AKCEPTOWANA ODPOWIEDŹ! @janos, właśnie zaoszczędziłeś mi godzin bólu głowy! Jeśli kiedykolwiek przyjedziesz do Indii, zabiorę cię na piwo!
Roopesh Shenoy
1
Lub: git svn fetch --all.
kenorb
1
Ta odpowiedź jest niesamowita, ponieważ odpowiada na około 7 pytań, na które nie mogłem znaleźć odpowiedzi, i robi to bez napisania 6-stronicowej narracji.
Droj
53

Wygląda na to, że po prostu potrzebowałem git svn fetch; jakoś przekonałem się, że ściągnę całe repo zamiast samych zmian.

Hank Gay
źródło
7
@mitjak Dlaczego to nie jest poprawna odpowiedź, jeśli jest to rozwiązanie? Nie rozumiem subtelności odpowiedzi.
rholmes
„rozwiązanie” może nie „rozwiązanie”
slf
1
@rholmes: Jestem prawie pewien, że mitjak oznacza, że ​​to rozwiązanie twojego problemu, ale nie odpowiedź na zadane pytanie. (Ponieważ zadałeś niewłaściwe pytanie; ponieważ wtedy źle zinterpretowałeś problem).
Mike Nelson
Działa to wtedy, gdy gałąź istniała w momencie sklonowania repozytorium SVN w git. Nie zadziała, jeśli gałąź w repozytorium svn została później utworzona.
Petr Gladkikh
3
Działa dobrze, gdy gałąź została utworzona po klonie, robię to cały czas.
Tim Gautier,
15

Może jakoś to pomieszałem, ale postępowałem zgodnie z instrukcjami zawartymi w odpowiedzi Vjangusa i prawie się udało. Jedynym problemem było to, że Newbranch nie wydawał się być rozgałęziony z pnia. W gitk było to jakby „pływanie” na własną rękę; nie miał wspólnego przodka z pniem.

Rozwiązaniem tego było:

  1. Znajdź SHA1 ostatniego zatwierdzenia, które wydarzyło się na linii głównej przed utworzeniem gałęzi.
  2. Znajdź SHA1 pierwszego zatwierdzenia w nowej gałęzi (prawdopodobnie jest to komunikat „Utworzono nową gałąź, skopiowano z pnia @ 12345” lub coś w tym rodzaju)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- nie powinno być wyjścia. Jeśli jest wyjście, być może wybrano nieprawidłowe zatwierdzenia.
  4. git checkout local-newbranchpotem git rebase <sha1 from step 1>. Spowoduje to local-newbranchzmianę bazy na nowe drzewo, ale remotes/newbranchnadal będzie rozłączone.
  5. Przejdź do pliku .git/refs/remotes/newbranchi edytuj go, aby zawierał pełny SHA1 nowego zatwierdzenia (w wersji bazowej newbranch), który odpowiada staremu zatwierdzeniu, na które obecnie wskazuje. (A może użyj git-update-ref refs/remotes/newbranch <new-SHA>. Dziękuję inger.)
  6. Następnym razem, kiedy git svn dcommitsię newbranch, dostaniesz kilka wiadomości o nim aktualizujących jakiś dziennik. Myślę, że to normalne.

Zalecam utrzymywanie gitk --allotwartego przez cały czas i odświeżanie go często, aby śledzić to, co robisz. Nadal jestem trochę nowy w git i git svn, więc proszę zasugerować ulepszenia tej metody.

MatrixFrog
źródło
2
Dzięki, to brzmi użytecznie. Około 5. prawdopodobnie „git-update-ref refs / remotes / newbranch <new-SHA>” jest bezpieczniejszą opcją.
inger
Jeszcze raz spróbowałem sposobu Vjangusa i zadziałało idealnie. Zostawię to tutaj, ponieważ może być dla kogoś cenne ...
MatrixFrog
1
Rozwiązanie vjangus zawsze tworzy nową gałąź odłączoną od linii głównej. Zakładam, że dzieje się tak z powodu tego, że sam SVN nie ma pojęcia, w jaki sposób kopiowana jest rzeczywista zawartość.
bogdan.mustiata
Moje doświadczenie z dużą repozytorium git-svn jest takie, że gałęzie svn są zawsze tworzone w git odłączonym od pnia. Powinien być jakiś sposób na ich połączenie, ale nie zastanawiałem się nad tym. AFAIK, nie możesz zmienić podstawy gałęzi git, która jest połączona z gałęzią svn, ponieważ to zepsuje logikę dcommit. Właśnie nauczyliśmy się z tym żyć.
Spencer
7

Uproszczenie odpowiedzi Vjangusa:

Jeśli używasz standardowego układu w SVN i wykonałeś zwykłą inicjalizację svn, git-svn wykona konfigurację za Ciebie. Właśnie:

  1. Znajdź wersję kopii oddziału w SVN
  2. Pobierz tę wersję za pomocą git-svn
  3. Utwórz nowy zdalny lokalny oddział śledzenia

Przykład. Adres URL SVN to svn+ssh://[email protected]/repo. Oddział SVN, którego szukam, to newbranch. Lokalny oddział git (śledzenie zdalne newbranch) będzie git-newbranch.

Krok 1: znajdź wersję kopii oddziału

    # svn log - stop-on-copy svn + ssh: //[email protected]/repo/branches/newbranch | ogon -4
    r7802 | ktoś | 2014-03-21 18:54:58 +0000 (Pt, 21 marca 2014) | 1 linia

    rozgałęzienie HEAD do newbranch
    -------------------------------------------------- ----------------------

Zatem punktem rozgałęzienia w SVN jest wersja 7802.

Krok 2: Pobierz wersję

    # git svn fetch -r 7802
    Znaleziony możliwy punkt rozgałęzienia: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Znaleziono oddział nadrzędny: (referencje / piloty / bagażnik) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Podążając za rodzicem do_switch
    Pomyślnie śledzono rodzica
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (referencje / piloty / newbranch)

git-svn wykonał całą pracę i teraz wie o pilocie:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c referencje / piloty / newbranch

Krok 3: Utwórz nowy oddział lokalny śledzący oddział zdalny:

    # git checkout -b git-newbranch -t newbranch
    Sprawdzanie plików: 100% (413/413), gotowe.
    Oddział git-newbranch skonfigurowany do śledzenia lokalnych referencji / pilotów / newbranch.
    Przeniesiono do nowej gałęzi „git-newbranch”
Gil Hamilton
źródło
Postępowanie w końcu pozwoliło mi zrozumieć ( show-refjest bezcenne)! Dla każdego, kto utknął z nieprawidłowymi odniesieniami do zdalnych gałęzi, możesz je usunąć (musiałem to zrobić, git branch -d newbrancha następnie wymusić usunięcie katalogu referencyjnego .git/svn/refs/remotes/newbranch), a następnie zacząć od nowa w kroku 2 (powyżej).
tutuDajuju
5

Nie znalazłem żadnej dokumentacji na temat tej funkcji, ale wygląda na to, że konfiguracja git svn obsługuje wiele wpisów pobierania. W ten sposób możesz również dodawać gałęzie osobno, bez potrzeby dodawania kolejnego wpisu zdalnego repozytorium svn do swojej konfiguracji ani używania symboli wieloznacznych, aby uzyskać wszystkie gałęzie określonego katalogu.

Załóżmy, że twoje drzewo SVN jest naprawdę paskudne, mając wiele gałęzi bez logiki co do ich lokalizacji, np. Mając gałęzie i podkatalogi zawierające bardziej rozgałęzione.

to znaczy

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

i po prostu chcesz ręcznie wybrać niektóre gałęzie, które zostaną włączone do Twojego repozytorium git.

Możesz najpierw zainicjować swoje repozytorium tylko z pniem bez żadnych dodatkowych gałęzi:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Następnie powinieneś zobaczyć następującą konfigurację:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

kiedy chcesz pobrać nowy oddział z MyRepo, możesz po prostu dodać nowe wpisy pobierania do konfiguracji poprzez:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Lub możesz edytować tę samą konfigurację w .git / config

Aby pobrać nowe gałęzie po dodaniu ich do konfiguracji, po prostu uruchom:

git svn fetch -r 10000:HEAD

[Edytuj] Czasami wydaje się konieczne uruchomienie pobierania z parametrem --all, aby pobrać nowo dodane gałęzie:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
źródło
4

Zamiast zajmować się dziwactwami git-svn, możesz wypróbować SubGit .

Trzeba zainstalować SubGit w repozytorium Subversion. Następnie można użyć standardowego przepływu pracy git zamiast specjalnych poleceń git-svn:

  1. Wprowadzanie nowych zatwierdzeń:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Pobieranie nadchodzących zmian

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Tworzenie nowego oddziału:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Więcej informacji znajduje się w dokumentacji SubGit .

vadishev
źródło
1
Wadą SubGit jest to, że tworzy dwa repozytoria - jedno svn i jedno „cień” repozytorium git. Może to stanowić problem dla ogromnych repozytoriów SVN ...
Udo,
@Udo, jeśli repozytorium SVN ma kilka projektów, można określić tylko jeden z nich i zsynchronizować je z repozytorium Git. W takim przypadku nie ma potrzeby konwertowania całego repozytorium Subversion na Git. Ale jeśli ktoś ma ogromny projekt SVN w tym repozytorium, można przekonwertować nie całą historię tego repozytorium, ale historię zaczynając od jakiejś minimalnej wersji. Pozwala to zmniejszyć rozmiar przetłumaczonego repozytorium Git.
vadishev
1
@Udo - każda firma, która nie chce kupować swojego serwera repozytoriów na dysku twardym, ma swoje priorytety. Ale większość miejsc z ogromnymi repozytoriami traktuje swoje repozytoria dość poważnie, a wymagania dotyczące miejsca na dysku dla repozytoriów nie są na ogół poważnym problemem, nawet dla firm z dziesięcioleciami historii i dziesiątkami milionów linii kodu i setkami tysięcy poprawek. Jest to najbardziej konkretna forma ich podstawowych zasobów intelektualnych firmy, a miejsce na dysku jest dość tanie. Może to powodować potrzebę uaktualnienia kontrolera RAID, ale nawet wzrost wydajności ...
Bob Kerns
@Bob Kerns - Chodzi o to, że SVN i Git „pod względem wielkości” nie są kompatybilne. To nie jest kwestia miejsca na dysku. Ale możesz pracować z ogromnym repozytorium SVN, ponieważ zwykle musisz wyewidencjonować tylko kilka plików / projektów. Ale nie można sklonować ogromnego repozytorium Git - przynajmniej nie sprawia to przyjemności ;-) Przez „ogromny” mam na myśli kilka koncertów.
Udo
2

Aby dodać do odpowiedzi vjangusa, która pomogła mi, uznałem również za przydatne dodanie przeszczepów git, aby związać gałęzie z pniem w odpowiednim punkcie - pozwalając gitowi zobaczyć historię i poprawnie połączyć.

Jest to po prostu przypadek dodania linii do .git/info/graftsskrótów:

<initial branch commit> <parent commit in trunk>

na przykład.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Kredyt na http://evan-tech.livejournal.com/255341.html

(Dodałbym to jako komentarz, ale nie mam wystarczającej reputacji).

Haddon CD.
źródło
0

Jeśli nie wyewidencjonujesz prawidłowego układu, nie będziesz w stanie wyewidencjonować zdalnego oddziału.

Tym się właśnie zajmuję:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Następnie możesz przejść do zdalnego oddziału:

git checkout --track -b branch_name branch_name

Następnie zostaniesz automatycznie przełączony do oddziału.

MikeHoss
źródło