web-dev-qa-db-fra.com

Travailler pour échouer "Clone Git Svn" (nécessitant une histoire complète)

Je souhaite convertir un sous-répertoire de référentiel de subversion (indiqué par module ici) dans un référentiel GIT avec une histoire complète. Il existe de nombreux opérations svn copy (les personnes subversion les appellent des succursales) dans l'historique de mon référentiel Subversion. La stratégie de version a été celle après chaque version ou d'autres branches créées, l'ancienne URL est laissée inutilisée et la nouvelle URL remplace l'ancien pour contenir le travail.

De manière optimale, par ma lecture, on dirait que cela devrait faire l'affaire:

$ git svn clone --username=mysvnusername --authors-file=authors.txt \
    --follow-parent \
    http://svnserver/svn/src/branches/x/y/apps/module module

(où branches/x/y/ décrit la nouvelle branche). Mais j'ai eu une erreur qui ressemble à quelque chose comme ça:

W: Ignoring error from SVN, path probably does not exist: (160013): Filesystem has no item: '/svn/src/!svn/bc/100/branches/x/y/apps/module' path not found
W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.

( Mise à jour: Ajout d'une option --no-minimize-url à ce qui précède ne supprime pas le message d'erreur.)

Le répertoire module Obtenez créé et peuplé, mais l'historique de subversion au-delà du Dernier svn copy commit n'est pas importé (le référentiel git créé finit par avoir seulement deux commits lorsque je m'attendais à des centaines).

La question est de savoir comment exporter l'historique complet de la subversion en présence de cette situation?

Cause possible

  1. Recherche du message d'erreur, j'ai trouvé ceci: Checkout git-svn anonyme échoue avec -s qui est lié à ce problème de subversion: http://subversion.tigris.org/issues/show_bug .cgi? id = 3242

    Ce que je comprends par ma lecture, quelque chose dans Subversion 1.5 a changé sur la manière dont le client accède au référentiel. Avec une nouvelle subversion, s'il n'y a pas d'accès en lecture à certains super répertoires du chemin de l'URL (true pour moi, svn ls http://svnserver/svn échoue avec 403 Forbidden), puis nous échouons avec certaines opérations de subversion.

  2. Jeff Fairley dans sa réponse souligne que les espaces de l'URL de Subversion pourraient également causer ce message d'erreur (confirmé par l'utilisateur Owen). Regardez sa solution pour voir comment il a résolu le cas si votre git svn clone échoue pour le même Resson.

  3. Dejay Clayton dans sa réponse révèle que si les composants de sous-répertoire les plus profonds des URL de la branche et des étiquettes SVN sont également nommés (par exemple, .../tags/release/1.0.0 et .../branches/release-candidates/1.0.0), cette erreur pourrait se produire.

26
FooF

J'ai rencontré ce problème lorsque j'avais des sous-répertoires nommés à l'intérieur des branches ou des balises.

Par exemple, j'ai eu des tags candidates/1.0.0 et releases/1.0.0, et cela a provoqué l'erreur documentée parce que le sous-répertoire 1.0.0 apparaît dans les deux candidates et releases.

Par - GIT-SVN Docs :

Lorsque vous utilisez plusieurs branches ou --tags, Git SVN ne gère pas automatiquement les collisions de noms (par exemple, si deux branches de différents chemins ont le même nom, ou si une branche et une balise ont le même nom). Dans ces cas, utilisez INIT pour configurer votre référentiel git puis, avant votre première extraction, modifier le fichier $ git_dir/config pour que les branches et les balises soient associées à des espaces de noms différents.

Ainsi, alors que la commande suivante a échoué à cause de la même manière nommée candidates et releases balises:

git svn clone --authors-file=../authors.txt --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/candidates \
    --tags=/releases --tags=/tags -r 100:HEAD \
    --prefix=Origin/ \
    svn://example.com:3692/my-repos/path/to/project/

la séquence de commandes suivante a fonctionné:

git svn init --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/tags \
    --prefix=Origin/ \
    'svn://example.com:3692/my-repos/path/to/project/'

git config --add svn-remote.svn.tags \
    'path/to/project/candidates/*:refs/remotes/Origin/tags/Candidates/*'

git config --add svn-remote.svn.tags \
    'path/to/project/releases/*:refs/remotes/Origin/tags/Releases/*'

git svn fetch --authors-file=../authors.txt -r100:HEAD

Notez que cela ne fonctionnait que parce qu'il n'y avait pas d'autres conflits dans branches et tags. S'il y en avait, j'aurais dû devoir les résoudre de la même manière.

Après avoir correctement cloné le référentiel SVN, j'ai ensuite exécuté les étapes suivantes afin de: Tournez les balises SVN en balises GIT; Tour trunk dans master; transformer les autres références dans des branches; et déplacer des chemins distants:

# Make tags into true tags
cp -Rf .git/refs/remotes/Origin/tags/* .git/refs/tags/
rm -Rf .git/refs/remotes/Origin/tags

# Make other references into branches
cp -Rf .git/refs/remotes/Origin/* .git/refs/heads/
rm -Rf .git/refs/remotes/Origin
cp -Rf .git/refs/remotes/* .git/refs/heads/ # May be missing; that's okay
rm -Rf .git/refs/remotes

# Change 'trunk' to 'master'
git checkout trunk
git branch -d master
git branch -m trunk master
7
Dejay Clayton

Pas une réponse complète, mais peut-être l'extrait que vous manquez (je suis intéressé à migrer aussi bien, j'ai donc trouvé cette partie du puzzle).

Lorsque vous regardez la Documentation de git-svn , vous trouverez l'option suivante:

--no-minimize-url 

Lors du suivi de plusieurs répertoires (à l'aide de --STDlayout, --Branches ou --Tags Options), Git SVN tentera de se connecter à la racine (ou au niveau autorisé le plus élevé) du référentiel de subversion. Cette valeur par défaut permet un meilleur suivi de l'historique si des projets entiers sont déplacés dans un référentiel, mais peuvent causer des problèmes sur des référentiels où des restrictions d'accès en lecture sont en place. Passage --No-Minimize-URL permettra à GIT SVN d'accepter des URLS, sans tenter de se connecter à un répertoire de niveau supérieur. Cette option est désactivée par défaut lorsque une seule URL/branche est suivie (cela ferait peu de bien).

Cela correspond à la situation que vous avez, de sorte que git svn N'essaie pas de lire un niveau supérieur de l'arborescence de répertoire (qui sera bloqué).

Au moins vous pourriez essayer d'essayer ...

6
mliebelt

J'ai récemment migré une longue liste de référentiels SVN en Git et vers la fin courait dans ce problème. Notre structure SVN était jolie bâclée, alors j'ai dû utiliser --no-minimize-url un peu. Typiquement, je dirais une commande comme:

$ git svn clone http://[url]/svn/[repo]/[path-to-code] \
            -s --no-minimize-url \
            -A authors.txt

Les dernières migrations que j'ai couru ont eu un espace dans l'URL. Je ne sais pas si c'était l'espace ou autre chose, mais j'avais la même erreur que vous voyiez. Je ne voulais pas entrer dans la modification des fichiers de configuration si je n'avais pas eu et j'ai fini par trouver une solution. J'ai fini par sauter le -s --no-minimize-url options en faveur de déclarer explicitement les chemins différemment.

$ git svn clone http://[url]/svn/[repo]/ \
            --trunk="/[path-to-code]/trunk" \
            --branches="/[path-to-code]/branches" \
            --tags="/[path-to-code]/tags" \
            -A authors.txt \
            --follow-parent
  • Notez que j'ai ajouté --follow-parent De votre exemple, mais je ne suis pas sûr que cela a fait une différence.
  • N'oubliez pas que ces repos avaient des espaces en eux, d'où la "" autour des chemins du tronc/des branches/des tags.
2
Jeff Fairley

[-Je me rends compte que cela devrait être un commentaire sur la réponse de Jeff Fairley, mais je n'ai pas la réputation de la publier comme tel. Puisque l'affiche originale a demandé une confirmation que l'approche a fonctionné que je lui fournis une réponse.]

Je peux confirmer que sa solution fonctionne pour le problème qu'il (et i) a couru causé par des espaces sur le chemin. J'ai eu les mêmes exigences (cloner un seul module d'un SVN Repo avec l'historique), sauf que je n'avais aucune branche ni étiquettes à craindre de ce que ce soit.

J'ai essayé plusieurs permutations de fournir le chemin complet du module de l'URL (par exemple en utilisant --no-minimise-url, en précisant --trunk ou --stdlayout) sans succès. Pour moi, le résultat était généralement un repo git avec un journal d'historique complet mais aucun fichier que ce soit. Cela peut ou non être le même problème que FOOF rencontré (aucun accès en lecture dans SVN), mais il était certainement causé par une place dans le chemin de mon module.

Essayer à nouveau avec seulement la base de repo SVN comme URL et le chemin de mon module en --trunk travaillé parfaitement. Ensuite, mon .git/config ressemble à ceci:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        loggallrefupdates = true
        symlinks = false
        ignorecase = true
        hideDotFiles = dotGitOnly
[svn-remote "svn"]
        url = https://[url]/svn/[repo]
        fetch = trunk/[path-to-code]:refs/remotes/trunk
[svn]
        authorsfile = ~/working/authors-transform.txt

et ultérieur git et git svn Les commandes ne jettent aucune erreur. Merci jeff!

1
Owen

[Ceci est l'affiche originale parlant l'écriture. Le ci-dessous était mis à jour à la question, mais comme il résolvait le cas - bien que peu satisfaisants à mon goût - je le posterai comme une réponse sans une meilleure solution.]

Je n'aime pas ça, mais j'ai fini par faire clone _ divisé dans init et fetch avec une modification de .git/config entre (repopath=apps/module, gitreponame=module):

$ git svn init--username=mysvnusername \
            --branches=/src/branches/ \
            --trunk=/src/trunk/${repopath} \
            --tags=/src/tags/ \
            http://svnserver/svn/src ${gitreponame}
$ cd ${gitreponame}
$ sed -i.bak "s|*:|*/${repopath}:|" .git/config
$ git svn fetch --authors-file=../authors.txt --follow-parent

Je ne pouvais pas trouver comment spécifier les succursales pour la migration sous-répertoire avec git svn - D'où l'édition du .git/config déposer. Le diff de difformité unifié suivant illustre l'effet de la modification avec sed:

 [svn-remote "svn"]
        url = http://svnserver/svn/src
        fetch = trunk/apps/module:refs/remotes/trunk
-       branches = branches/*:refs/remotes/*
-       tags = tags/*:refs/remotes/tags/*
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

Comme le réel souhaité HEAD était dans une autre URL, j'ai fini simplement en ajoutant un autre [svn-remote] section à .git/config:

+ [svn-remote "svn-newest"]
+       url = http://svnserver/svn/src
+       fetch = branches/x/y/apps/module:refs/remotes/trunk
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

(Dans une expérience réelle, j'ai également ajouté ici certaines branches qui n'ont pas été ramassées par la première extraction) et récupérant à nouveau:

$ git svn fetch --authors-file=../authors.txt --follow-parent svn-newest

De cette façon, j'ai fini par avoir l'historique de subversion complète émigré au référentiel Git nouvellement généré.

Note-1 : J'aurais probablement pu viens de dire à mon "tronc" d'être branches/x/y/apps/module comme la signification de "coffre" pour git-svn semble essentiellement avoir la signification de git HEAD (Concepts de Subversion du tronc, des branches, des balises ne sont pas une base technique profonde, elles sont une question de convention socialement acceptée).

Note-2 : probablement --follow-parent n'est pas requis pour git svn fetch, mais je n'ai aucun moyen de savoir ni d'expérimenter maintenant.

Note-3 : tandis que la lecture antérieure de SVN2Git qui semble être une enveloppe sur git-svn J'ai échoué à voir la motivation, mais voyant la présentation désordonnée des tags, je l'obtiens en quelque sorte. Je voudrais essayer svn2git La prochaine fois si je devais essayer de le faire à nouveau.

P.s. C'est une façon plutôt délicat de faire l'opération. Problème secondaire ici (pourquoi l'édition du .git/config par externe était requis) semble être que

  1. Les branches de subversion n'ont aucune signification technique essentielle ( branches et Tags en subversion ne sont que A des étiquettes acceptées socialement congérées pour un Copier le système de fichiers versionné conjointement avec la convention "standard" ou autrement accepté socialement sur laquelle les copies sont effectuées - coffre n'a pas non plus de sens technique), et
  2. git svn La mise en œuvre suppose strictement les conventions de subversion sociale à suivre à un degré (ce qui n'est pas possible si vous souhaitez simplement migrer un sous-répertoire et non le référentiel de subversion entiers).

TODO: Il serait utile d'avoir le format de la .git/config Fichier expliqué ici car il se rapporte à git svn - Par exemple, j'ai maintenant (après une et une demi année d'écriture de la réponse originale) aucune idée de ce que le [svn-remote "svn-newest"] signifie ci-dessus. L'approche pourrait également être automatisée en écrivant un script, mais cela dépasse mon intérêt actuel dans le problème et je n'ai pas accès au référentiel de subversion d'origine ni à la réplication du problème.

1
FooF