git-svn: qual è l'equivalente di `svn switch --relocate`?


88

Un repository svn di cui sto eseguendo il mirroring tramite git-svn ha cambiato URL.

In vanilla svn faresti solo svn switch --relocate old_url_base new_url_base.

Come posso farlo usando git-svn?

La semplice modifica dell'URL svn nel file di configurazione non riesce.


Dovresti provare e possibilmente accettare questa risposta: stackoverflow.com/a/4061493/1221661
Fritz

Risposta più aggiornata: stackoverflow.com/a/40523789/537554 . Stessa domanda, ma posta dal punto di vista di un utente Git.
ryenus

Risposte:


61

Questo gestisce abbastanza bene la mia situazione:

https://git.wiki.kernel.org/index.php/GitSvnSwitch

Ho clonato usando il file://protocollo e volevo passare al http://protocollo.

Si è tentati di modificare l' urlimpostazione nella [svn-remote "svn"]sezione di .git/config, ma di per sé non funziona. In generale è necessario seguire la seguente procedura:

  1. Cambia l' urlimpostazione svn-remote con il nuovo nome.
  2. Corri git svn fetch. Questo deve recuperare almeno una nuova revisione da svn!
  3. Cambia l' urlimpostazione di svn-remote indietro all'URL originale.
  4. Corri git svn rebase -lper fare un rebase locale (con le modifiche apportate con l'ultima operazione di recupero).
  5. Modifica l' urlimpostazione di svn-remote con il nuovo URL.
  6. Ora, git svn rebasedovrebbe funzionare di nuovo.

Le anime avventurose potrebbero voler provare --rewrite-root.


2
per essere onesti, questo in realtà non è riuscito per me, e ho finito per ri-clonare il repo. È difficile convincere git a gestirlo quando la directory svn viene rinominata.
Gregg Lind

Preferirei accettare un resoconto più dettagliato, ma abbastanza giusto, lo accetterò fino a quando non arriverà una nuova risposta.
kch

2
Ecco un'altra descrizione di quella procedura: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

il link fornito nella risposta accettata è obsoleto e quello nuovo al momento è: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Ho seguito il "caso generale" ed è stato semplice e davvero ha funzionato bene.
TcMaster

2
@TcMaster: ha funzionato anche per me ... ma è per questo che le risposte non dovrebbero contenere solo link, diventano obsolete e diventano inutili ... Aggiungerò una risposta wiki della comunità.
UncleZeiv

37

Puoi vedere se quanto segue funziona bene:

  1. Se svn-remote.svn.rewriteRootnon esiste nel file di configurazione ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Se svn-remote.svn.rewriteUUIDnon esiste nel file di configurazione:

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    La currentRepositoryUUIDpuò essere ottenuto da .git/svn/.metadata.

  3. git config svn-remote.svn.url <newRepositoryURL>


Fantastico - grazie, ha funzionato benissimo per me (clonato tramite file://, passa a svn+ssh); notando solo che: questa procedura non ha bisogno di "recuperare almeno una nuova revisione da svn"; anche ./.git/svn/.metadataafter first svn rebasecontiene l' <newRepository>as reposRoot- ma questo non è sufficiente per rimuovere le rewrite*chiavi da .git/config; quindi quelle chiavi dovrebbero essere tenute permanentemente lì, per quanto ne so.
sdaau

1
Ha funzionato anche per me, come un incantesimo. L'OP dovrebbe provare questo e ottenerlo come risposta corretta.
Rafareino

Perfetto. Avevo un grande progetto con migliaia di commit nella cronologia, quindi un nuovo clone avrebbe distrutto la cronologia (o avrebbe impiegato molto tempo per il checkout). Sto usando svn+ssh://e il nostro server svn ha appena cambiato dominio da .sea .comper disinfettare la nostra denominazione interna.
UlfR

Ha funzionato a meraviglia per me. Aveva un repository di 2 anni con migliaia di commit, il repository è stato spostato su un nuovo host, quindi questo ha evitato un (temuto) clone svn completo.
David Victor

21

Sfortunatamente la maggior parte dei collegamenti in queste risposte non funzionano, quindi duplicherò un po 'di informazioni dal wiki di git per riferimento futuro.

Questa soluzione ha funzionato per me:

  • Modificare il svn-remote url(o il fetchpercorso) in .git/configper puntare al nuovo dominio / url / percorso

  • Esegui git git svn fetch. Questo deve recuperare almeno una nuova revisione da svn!

  • Se provi git svn rebaseora, riceverai un messaggio di errore come questo:

    Unable to determine upstream SVN information from working tree history
    

    Penso che ciò sia dovuto git svnal fatto che è confuso dal fatto che il tuo ultimo commit prima del recupero avrà un git-svn-idpuntamento al vecchio percorso, che non corrisponde a quello trovato in .git/config.

  • Come soluzione alternativa, modifica svn-remote url(o fetchpercorso) nuovamente il dominio / URL / percorso originale

  • Ora esegui di git svn rebase -lnuovo per eseguire un rebase locale con le modifiche apportate con l'ultima operazione di recupero. Questa volta sarà lavorare, apparentemente perché git svnnon possa essere confuso con il fatto che l' git-svn-iddel nuovo capo non corrisponde a quello trovato in .git/config.

  • Infine, cambia svn-remote url(o fetchpercorso) di nuovo al nuovo dominio / url / percorso

  • A questo punto git svn rebasedovrebbe funzionare di nuovo!

Le informazioni originali sono state trovate qui .



2

git filter-branch

Questo script , tratto da un post di un blog , ha funzionato per me. Fornisci l'URL del repository vecchio e nuovo come parametro, proprio come per svn switch --relocate.

Lo script chiama git filter-branchper sostituire gli URL di Subversion nei git-svn-idmessaggi di commit, aggiorna .git/confige aggiorna anche i git-svnmetadati ricreandoli usando git svn rebase. Sebbene git svn clonepossa essere la soluzione più robusta, l' filter-branchapproccio funziona molto più velocemente per grandi archivi (ore rispetto a giorni).

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase

1

git_fast_filter

Eppure più veloce di git-filter-branch(cioè minuti invece di ore), ma simile nello spirito, è da usare git_fast_filter. Tuttavia, ciò richiede un po 'più di codice e non esiste una soluzione pronta per l'uso. Al contrario git-filter-branch, questo creerà un nuovo repo da uno vecchio . Si presume che masterpunti all'ultimo commit SVN.

  1. Clone git_fast_filterdal repository Gitorious.
  2. Crea uno script Python nella stessa directory in cui hai clonato in git_fast_filterbase a questo Gist , imposta il bit eseguibile usando chmod +x. Adatta il vecchio e il nuovo percorso del repository. (Anche i contenuti della sceneggiatura vengono incollati di seguito).
  3. Inizializza un nuovo repository di destinazione utilizzando git init, cambia la directory di lavoro in questo nuovo repository.
  4. Esegui la seguente pipe:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Copia .git/confige forse altri file pertinenti .git/infodal vecchio repository al nuovo repository.

  6. Rimuovi .git/svn.
  7. Renditi git-svnconto della nuova mappatura del numero di revisione

    1. Eseguire git branch refs/remotes/git-svn master

      • I tuoi telecomandi git-svn potrebbero essere chiamati diversi da refs/remotes/git-svn, consult .git/config, svn-remotesezioni
    2. Esegui git svn info. Se questo comando si blocca, qualcosa non va. Dovrebbe ricostruire la mappatura del numero di revisione.

    3. Rimuovi il ramo falso refs/remotes/git-svn, verrà ricreato dagit-svn

  8. Sincronizza chiamando git svn rebase.

Di seguito è riportato il contenuto di commit_filter.py, sostituire i valori di IN_REPOe OUT_REPOcome appropriato:

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()

0

La git svn rebase -lsoluzione di cui sopra non ha funzionato per me. Ho deciso di farlo in un modo diverso:

  1. Clona il vecchio repository SVN in git repo olde il nuovo SVN in git reponew
  2. Recupera oldinnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newin cima old(dovrebbe avere successo perché gli alberi nella radice di newe nella punta di oldsono identici)
    • git checkout master(Si presume che il masterramo punti alla testa SVN. Questo sarà il caso di un clone pulito; altrimenti dcommit prima di iniziare.)
    • git rebase --root --onto old
  4. Ricostruisci i metadati git-svn di newper tenere conto del rebase
    • git update-ref --no-deref refs/remotes/git-svn master(regola il riferimento remoto a seconda di come hai clonato, ad esempio potrebbe essere refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. Inizi con un nuovo clone della nuova posizione con una nuova? Se sì, perché non hai finito a quel punto? 2. Se ribassi nuovo su vecchio, i tuoi vecchi commit menzionano tutti il ​​vecchio URL nella loro voce di log dei commit svn-id? 3. Esiste una documentazione salvata per rimuovere .git / svn? (3b: quale comando sta ricostruendo i metadati git-svn, git svn info?)
Micha Wiedenmann,

0

Sulla base di alcune delle altre risposte a questa domanda, ho escogitato uno script Ruby che gestisce il trasferimento di git-svn. Puoi trovarlo su https://gist.github.com/henderea/6e779b66be3580c9a584 .

Gestisce il trasferimento senza estrarne un'altra copia e gestisce anche il caso in cui sono presenti modifiche non inviate in uno o più rami (poiché ciò interrompe la logica normale). Usa cose dalla risposta git filter-branch (per la logica principale) e la risposta sulla copia di rami da un'istanza del repository a un'altra (per copiare rami con modifiche non inviate).

L'ho usato per riposizionare un gruppo di repository git-svn che ho per lavoro, e questa versione dello script (ho passato innumerevoli iterazioni) sembra funzionare per me. Non è super veloce, ma sembra che gestisca tutti i casi che ho riscontrato e si traduca in un repository completamente riposizionato.

Lo script offre la possibilità di creare una copia del repository prima di apportare modifiche, quindi è possibile utilizzare questa opzione per creare un backup. La creazione di una copia è necessaria se sono presenti modifiche non inviate in qualsiasi ramo.

Lo script non utilizza gemme o altre librerie non incluse nella normale installazione di MRI Ruby. Utilizza le librerie readline e fileutils incluse in MRI.

Spero che il mio script si riveli utile a qualcun altro. Sentiti libero di apportare modifiche allo script.

NOTA: Ho testato questo script solo con git 2.3.0 / 2.3.1 e Ruby 2.2.0 su OS X 10.10 Yosemite (poiché è l'ambiente che uso), ma mi aspetto che funzioni anche su altri ambienti. Nessuna garanzia su Windows, però.

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.