Come faccio a dire a git-svn di un ramo remoto creato dopo aver recuperato il repository?


193

Sto git-svnlavorando per lavorare contro il repository Subversion centrale della mia azienda. Di recente abbiamo creato un nuovo ramo di funzionalità nel repository centrale.

Come posso dirlo a Git? Quando corro git branch -rposso vedere solo i rami esistenti quando ho corso fetchcontro il repository Subversion per inizializzare il mio repository Git?


Risposte da qui: stackoverflow.com/questions/13376917/… potrebbe anche essere utile.
Tomasz Gandor,

Risposte:


294

Puoi aggiungere manualmente il ramo remoto,

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

3
semplicemente aggiungendo questo link alla documentazione come riferimento kernel.org/pub/software/scm/git/docs/git-svn.html
slf

1
Da .git / config è abbastanza facile capire come i rami remoti possono essere configurati da repository singoli / multipli.
Mikael Lepistö,

6
Se potessi votare questo come otto volte, lo farei. Infine, un modo per aggiungere un ramo svn che è stato aggiunto in una posizione non standard!
Tim Keating,

7
Vado fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.al passaggio di checkout git.
phpguru,

17
@phpguru Prova a rimuovere il flag dell'opzione -t in modo che diventi 'git checkout -b local-newbranch newbranch' non dimenticare di includere il prefisso del telecomando su newbranch (es. origin / newbranch).
mj1531,

96

Se vuoi tenere traccia di TUTTI i rami svn remoti, la soluzione è semplice come:

git svn fetch

Ciò recupererà TUTTI i rami remoti che non sono stati ancora recuperati.

Suggerimento extra: se inizialmente hai estratto solo il trunk e in seguito desideri tenere traccia di TUTTI i rami, modifica .git/configin modo che sia simile a questo e riesegui 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/*

I punti chiave urldovrebbero puntare alla radice del repository e i percorsi definiti in fetche branchesdovrebbero essere relativi url.

Se vuoi recuperare solo rami specifici invece di TUTTI, c'è un buon esempio in 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/*

Con le versioni precedenti di git-svn, una volta specificati i rami come questo, potresti non essere in grado di ottenere nuovi rami con git svn fetch. Una soluzione alternativa è l'aggiunta di più fetchrighe, in questo modo:

[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/*

Un'altra soluzione alternativa di @AndyEstes: modifica .git/svn/.metadatae modifica il valore branches-maxRevo tags-maxRevuna revisione prima che vengano creati rami o tag appena specificati. Una volta fatto questo, corri git svn fetchper tracciare il nuovo ramo remoto svn.


1
Se hai già recuperato la revisione su cui è stata eseguita la ramificazione svn prima di impostare tali impostazioni, potresti voler eseguire git svn reset.
kcm1700,

3
La modifica è .git/svn/.metadatastata molto utile! Stavo aggiungendo ulteriori rami nel mio .git/config, che git svn fetchnon hanno ripreso, perché il numero di revisione dei metadati era "troppo avanti". In un caso, è stato recuperato solo l'ultimo commit da un ramo. Mi sono liberato manualmente del ramo difettoso (rinominato .git/svn/refs/remotes/svn/qa/XYZin .git/svn/refs/remotes/svn/qa/XYZ~, lasciato cadere la sua esistenza in .git/packed-refs, ecc.) ... ho scelto un numero di revisione "precedente" per i metadati ... ho corso git svn fetchper ottenere finalmente una cronologia completa con un grafico corretto e connesso.
Starlocke,

8
QUESTA DOVREBBE ESSERE LA RISPOSTA ACCETTATA! @janos, mi hai appena risparmiato ore di mal di testa! Se mai verrai in India, ti porterò fuori per una birra!
Roopesh Shenoy,

1
Oppure: git svn fetch --all.
Kenorb,

1
Questa risposta è sorprendente, perché risponde a circa 7 domande alle quali non ho trovato risposta, e lo fa senza scrivere una narrativa di 6 pagine.
Droj,

53

Sembra che dovevo solo git svn fetch; in qualche modo mi ero convinto che avrei recuperato l'intero repository anziché solo le modifiche.


7
@mitjak Perché non è la risposta corretta, se è la soluzione? Non capisco la finezza della risposta.
rholmes,

'una soluzione' forse non 'la soluzione'
slf

1
@rholmes: sono abbastanza sicuro che mitjak significhi che questa è la soluzione al tuo problema ma non la risposta alla domanda che hai posto. (Perché hai fatto la domanda sbagliata; dato che hai interpretato male il problema in quel momento.)
Mike Nelson,

Funziona quando esisteva il ramo nel momento in cui hai clonato il repository svn in git. Non funzionerà se il ramo nel repository svn è stato creato in seguito.
Petr Gladkikh,

3
Funziona bene quando il ramo è stato creato dopo il clone, lo faccio sempre.
Tim Gautier,

15

Forse l'ho incasinato in qualche modo ma ho seguito le istruzioni nella risposta di Vjangus e ha quasi funzionato. L'unico problema era che Newbranch non sembrava essere ramificato dal tronco. In gitk, era un po '"fluttuante" da solo; non aveva antenati comuni con il tronco.

La soluzione a questo è stata:

  1. Trova SHA1 dell'ultimo commit eseguito sul trunk prima della creazione del ramo.
  2. Trova lo SHA1 del primo commit sul nuovo ramo (il messaggio è probabilmente "Creato nuovo ramo, copiato dal trunk @ 12345" o qualcosa del genere)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- non dovrebbe esserci output. Se c'è un output, potresti aver selezionato commit errati.
  4. git checkout local-newbranchallora git rebase <sha1 from step 1>. Questo si rinnoverà local-newbranchsul nuovo albero ma remotes/newbranchverrà comunque disconnesso.
  5. Vai al file .git/refs/remotes/newbranche modificalo per contenere l'intero SHA1 del nuovo commit (sul rebased newbranch) che corrisponde al vecchio commit a cui sta puntando. (O forse usare git-update-ref refs/remotes/newbranch <new-SHA>. Grazie inger.)
  6. La prossima volta che git svn dcommita newbranch, si otterrà un sacco di messaggi su di esso che aggiorna alcune registro. Questo è normale, penso.

Ti consiglio di rimanere sempre gitk --allaperto e di aggiornarlo spesso per tenere traccia di ciò che stai facendo. Sono ancora un po 'nuovo di git e git svn, quindi per favore suggerisci miglioramenti a questo metodo.


2
Grazie, sembra utile. Circa 5. probabilmente 'git-update-ref refs / remotes / newbranch <new-SHA>' è l'opzione più sicura.
inger

Ho appena provato di nuovo il modo di Vjangus e ha funzionato perfettamente. Lascio questo qui comunque poiché potrebbe essere prezioso per qualcuno ...
MatrixFrog,

1
La soluzione vjangus crea sempre il nuovo ramo disconnesso dal trunk. Suppongo che ciò sia dovuto al modo in cui SVN stesso non ha idea di come venga copiato il contenuto reale.
bogdan.mustiata,

La mia esperienza con un repository git-svn di grandi dimensioni è che i rami svn vengono sempre creati in git staccato dal trunk. Dovrebbe esserci un modo per collegarli, ma non ho avuto il tempo di capirlo. AFAIK, non puoi rifare il ramo git che è connesso al ramo svn, perché ciò rovinerebbe la logica di dcommit. Abbiamo appena imparato a conviverci.
Spencer

7

Una semplificazione della risposta di vjangus:

Se stai usando il layout standard in SVN e hai fatto il solito svn init, git-svn farà le cose di configurazione per te. Appena:

  1. Trova la revisione della copia del ramo in SVN
  2. Scarica quella revisione con git-svn
  3. Crea un nuovo telecomando per il monitoraggio delle filiali locali

Un esempio. L'URL SVN è svn+ssh://gil@svn.myplace.com/repo. La filiale SVN che sto cercando è newbranch. newbranchSarà il ramo git locale (monitoraggio remoto ) git-newbranch.

Passaggio 1: trova la revisione della copia del ramo

    # svn log --stop-on-copy svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch | coda -4
    r7802 | qualcuno | 21-03-2014 18:54:58 +0000 (Ven, 21 mar 2014) | 1 riga

    diramazione di HEAD verso Newbranch
    -------------------------------------------------- ----------------------

Quindi il punto di diramazione in SVN è la revisione 7802.

Passaggio 2: recuperare la revisione

    # git svn fetch -r 7802
    Trovato possibile punto di diramazione: svn + ssh: //gil@svn.myplace.com/repo/trunk => svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch, 7801
    Parent branch trovato: (refs / remotes / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Segue genitore con do_switch
    Genitore seguito con successo
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / telecomandi / newbranch)

git-svn ha fatto tutto il lavoro e ora conosce il telecomando:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / telecomandi / newbranch

Passaggio 3: crea la tua nuova filiale locale monitorando quella remota:

    # git checkout -b git-newbranch -t newbranch
    Verifica dei file: 100% (413/413), fatto.
    Branch git-newbranch istituito per tenere traccia dei riferimenti / telecomandi / newbranch.
    Passato a una nuova filiale "git-newbranch"

A seguito di ciò finalmente mi ha permesso di capire ( show-refè prezioso)! Per chiunque sia bloccato con riferimenti errati ai rami remoti, è possibile eliminarli (dovevo fare git branch -d newbranche quindi forzare la rimozione della directory di riferimento in .git/svn/refs/remotes/newbranch) e ricominciare dal passaggio 2 (sopra).
tutuDajuju,

5

Non ho trovato alcuna documentazione su questa funzione, ma sembra che la configurazione di git svn supporti più voci di recupero. In questo modo puoi anche aggiungere rami separatamente senza bisogno di aggiungere un'altra voce di repository svn remoto alla tua configurazione né usare i caratteri jolly per ottenere tutti i rami di una determinata directory.

Supponiamo che il tuo albero SVN sia davvero brutto con molti rami senza alcuna logica sul modo in cui si trovano, ad esempio con rami e sottodirectory contenenti più rami.

vale a dire

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

e vuoi solo selezionare manualmente alcuni dei rami da includere nel tuo repository git.

Puoi prima avviare il tuo repository con solo trunk senza rami aggiuntivi:

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

Dopodiché dovresti vedere la seguente configurazione:

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

quando vuoi recuperare un nuovo ramo da MyRepo puoi semplicemente aggiungere nuove voci di recupero alla configurazione:

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

Oppure puoi modificare la stessa configurazione in .git / config

Per recuperare i nuovi rami dopo averli aggiunti alla configurazione basta eseguire:

git svn fetch -r 10000:HEAD

[Modifica] A volte sembra necessario eseguire il recupero con il parametro --all per recuperare i rami appena aggiunti:

git svn fetch --all -r 10000:HEAD

4

Invece di gestire le stranezze di git-svn puoi provare SubGit .

Uno deve installare SubGit nel repository Subversion. Dopodiché si può usare il flusso di lavoro git standard invece di usare i comandi speciali git-svn:

  1. Spingendo nuovi commit:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Recupero delle modifiche in arrivo

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Creare una nuova filiale:

    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
    

Vedere la documentazione di SubGit per maggiori dettagli.


1
SubGit ha lo svantaggio di creare due repository: uno svn e un repository git "shadow". Questo potrebbe essere un problema per enormi repository SVN ...
Udo

@Udo se il repository SVN ha alcuni progetti, è possibile specificarne solo uno e sincronizzarlo con il repository Git. In questo caso non è necessario convertire l'intero repository Subversion in Git. Ma se uno ha un enorme progetto SVN in questo repository, si può convertire non l'intera storia di questo repository ma la storia a partire da una revisione minima. Ciò consente di ridurre le dimensioni del repository Git tradotto.
vadishev,

1
@Udo: qualsiasi azienda che non è disposta ad acquistare un server di repository su un disco rigido ha le proprie priorità incasinate. Ma la maggior parte dei luoghi con enormi repository prende i loro repository piuttosto seriamente, e i requisiti di spazio su disco per i repository non sono generalmente un grosso problema, anche per le aziende con decenni di storia e decine di milioni di righe di codice e centinaia di migliaia di revisioni. È la forma più concreta dell'azienda delle loro risorse intellettuali fondamentali e lo spazio su disco è piuttosto economico. Potrebbe innescare la necessità di aggiornare un controller RAID, ma anche così, l'aumento della produttività ...
Bob Kerns

@Bob Kerns - Il punto è che "dimensioni sagge" SVN e Git e non compatibili. Non è una questione di archiviazione su disco o giù di lì. Ma puoi lavorare con un enorme repository SVN perché di solito devi estrarre solo pochi file / progetti. Ma non puoi clonare un enorme repository Git - almeno non ci si diverte ;-) Per "enorme" intendo parecchi concerti.
Udo,

2

Per aggiungere alla risposta di Vjangus, che mi ha aiutato, ho anche trovato utile aggiungere utilizzare innesti git per legare i rami al tronco nel punto appropriato, consentendo a Git di vedere la cronologia ed eseguire correttamente le fusioni.

Questo è semplicemente un caso di aggiunta di una linea .git/info/graftscon gli hash:

<initial branch commit> <parent commit in trunk>

per esempio.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Ringraziamo http://evan-tech.livejournal.com/255341.html

(Aggiungo questo come commento, ma non ho abbastanza reputazione.)


0

Se non esegui il checkout con un layout valido, non potrai effettuare il checkout di una filiale remota.

Questo è ciò che faccio:

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

Successivamente, puoi passare a un ramo remoto:

git checkout --track -b branch_name branch_name

Quindi passerai automaticamente alla tua filiale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.