web-dev-qa-db-fra.com

git-svn: quel est l'équivalent de `svn switch --relocate`?

Un référentiel svn que je mets en miroir via git-svn a changé d'URL.

Dans Vanilla svn, vous feriez simplement svn switch --relocate old_url_base new_url_base.

Comment puis-je faire cela en utilisant git-svn?

La simple modification de l'URL svn dans le fichier de configuration échoue.

87
kch

Cela gère assez bien ma situation:

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

J'ai cloné en utilisant le file:// et souhaitait passer au http:// protocole.

Il est tentant de modifier le paramètre url dans le [svn-remote "svn"] section de .git/config, mais en soi, cela ne fonctionne pas. En général, vous devez suivre la procédure suivante:

  1. Basculez le paramètre svn-remote url vers le nouveau nom.
  2. Courir git svn fetch. Cela doit récupérer au moins une nouvelle révision de svn!
  3. Remplacez le paramètre svn-remote url par l'URL d'origine.
  4. Courir git svn rebase -l pour effectuer un rebase local (avec les modifications apportées lors de la dernière opération d'extraction).
  5. Remplacez le paramètre svn-remote url par la nouvelle URL.
  6. Maintenant, git svn rebase devrait fonctionner à nouveau.

Les âmes aventureuses voudront peut-être essayer --rewrite-root .

61
kch

Vous pouvez voir si les éléments suivants fonctionnent correctement:

  1. Si svn-remote.svn.rewriteRoot n'existe pas dans le fichier de configuration (.git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Si svn-remote.svn.rewriteUUID n'existe pas dans le fichier de configuration:

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

    currentRepositoryUUID peut être obtenu auprès de .git/svn/.metadata.

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

35
H Krishnan

Malheureusement, la plupart des liens dans ces réponses ne fonctionnent pas, donc je vais dupliquer un peu d'informations du git wiki pour référence future.

Cette solution a fonctionné pour moi:

  • Modifiez le svn-remoteurl (ou fetch chemin) dans .git/config pour pointer vers le nouveau domaine/url/chemin

  • Exécutez git git svn fetch. Cela doit récupérer au moins une nouvelle révision de svn!

  • Si vous essayez git svn rebase maintenant, vous obtiendrez un message d'erreur comme celui-ci:

    Unable to determine upstream SVN information from working tree history
    

    Je pense que c'est parce que git svn est troublé par le fait que votre dernier commit avant l'extraction aura un git-svn-id pointant vers l'ancien chemin, qui ne correspond pas à celui trouvé dans .git/config.

  • Pour contourner ce problème, modifiez svn-remoteurl (ou fetch chemin) vers le domaine/url/chemin d'origine

  • Exécutez maintenant git svn rebase -l à nouveau pour effectuer un rebasage local avec les modifications apportées lors de la dernière opération d'extraction. Cette fois, cela fonctionnera , apparemment parce que git svn ne sera pas dérouté par le fait que git-svn-id de la nouvelle tête ne correspond pas à celle trouvée dans .git/config.

  • Enfin, modifiez svn-remoteurl (ou fetch chemin) vers le nouveau domaine/url/chemin

  • À ce point git svn rebase devrait fonctionner à nouveau!

Les informations d'origine ont été trouvées ici .

21
UncleZeiv

Git svn s'appuie fortement sur l'URL svn. Chaque commit importé de svn a un git-svn-id qui inclut l'URL svn.

Une stratégie de relocalisation valide consiste à appeler git-svn clone sur le nouveau référentiel et fusionner les modifications dans cette nouvelle fermeture. Pour une procédure plus détaillée, consultez cet article:

http://www.sanityinc.com/articles/relocating-git-svn-repositories

3
Adam Alexander

git filter-branch

Ce script , tiré de ne entrée de blog , a fonctionné pour moi. Fournissez l'ancien et le nouveau URL de dépôt en tant que paramètre, comme pour svn switch --relocate.

Le script appelle git filter-branch pour remplacer les URL Subversion dans le git-svn-id dans les messages de validation, met à jour .git/config, et met également à jour git-svn métadonnées en les recréant à l'aide de git svn rebase. Tandis que git svn clone pourrait être la solution la plus robuste, le filter-branch L'approche fonctionne beaucoup plus rapidement pour les grands référentiels (heures vs jours).

#!/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
2
krlmlr

git_fast_filter

Pourtant, plus rapide que git-filter-branch (c.-à-d. minutes au lieu d'heures), mais similaire dans son esprit, consiste à utiliser git_fast_filter . Cependant, cela nécessite un peu plus de codage, et il n'existe aucune solution soignée prête à l'emploi. Contrairement à git-filter-branch, cela créera un nouveau dépôt à partir d'un ancien . Il est supposé que master pointe vers le dernier commit SVN.

  1. Cloner git_fast_filter du repo Gitorious.
  2. Créez un script Python dans le même répertoire où vous avez cloné git_fast_filter basé sur cet Gist , définissez le bit exécutable en utilisant chmod +x. Adaptez les anciens et nouveaux chemins de référentiel. (Le contenu du script est également collé ci-dessous.)
  3. Initialisez un nouveau référentiel cible à l'aide de git init, changez le répertoire de travail en ce nouveau dépôt.
  4. Exécutez le canal suivant:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Copie .git/config, et peut-être d'autres fichiers pertinents dans .git/info de l'ancien référentiel au nouveau référentiel.

  6. Retirer .git/svn.
  7. Faire git-svn au courant du nouveau mappage des numéros de révision

    1. Exécutez git branch refs/remotes/git-svn master

      • Vos télécommandes git-svn peuvent être appelées différemment de refs/remotes/git-svn, consulter .git/config, svn-remote sections
    2. Exécutez git svn info. Si cette commande se bloque, quelque chose ne va pas. Il devrait reconstruire le mappage du numéro de révision.

    3. Retirez la fausse branche refs/remotes/git-svn, il sera recréé par git-svn

  8. Synchronisez en appelant git svn rebase.

Voici le contenu de commit_filter.py, remplacez les valeurs de IN_REPO et OUT_REPO selon le cas:

#!/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()
1
krlmlr

Sur la base de certaines des autres réponses à cette question, j'ai trouvé un script Ruby qui gère la relocalisation de git-svn. Vous pouvez le trouver sur https: // Gist.github.com/henderea/6e779b66be3580c9a584 .

Il gère la relocalisation sans extraire une autre copie, et il gère même le cas où il y a des changements non poussés dans une ou plusieurs branches (car cela rompt la logique régulière). Il utilise des éléments de la réponse git filter-branch (pour la logique principale) et la réponse sur la copie des branches d'une instance du référentiel vers une autre (pour copier des branches avec des modifications non poussées).

Je l'ai utilisé pour déplacer un tas de dépôts git-svn que j'ai pour le travail, et cette version du script (j'ai traversé d'innombrables itérations) semble fonctionner pour moi. Ce n'est pas super rapide, mais il semble gérer tous les cas que j'ai rencontrés et entraîner un repo entièrement relocalisé.

Le script vous donne la possibilité de créer une copie du référentiel avant d'apporter des modifications, vous pouvez donc utiliser cette option pour créer une sauvegarde. La création d'une copie est requise si vous avez des modifications non poussées dans des branches.

Le script n'utilise pas de gemmes ou d'autres bibliothèques non incluses dans l'installation MRI normale Ruby installation. Il utilise les bibliothèques readline et fileutils incluses dans MRI.

J'espère que mon script sera utile à quelqu'un d'autre. N'hésitez pas à apporter des modifications au script.

REMARQUE: Je n'ai testé ce script qu'avec git 2.3.0/2.3.1 et Ruby 2.2.0 sur OS X 10.10 Yosemite (puisque c'est l'environnement que j'utilise), mais je m'attendrais à ce qu'il fonctionne également sur d'autres environnements. Aucune garantie sur Windows, cependant.

0
Eric Henderson

Ce qui précède git svn rebase -l la solution n'a pas fonctionné pour moi. J'ai décidé de procéder différemment:

  1. Clonez l'ancien dépôt SVN dans git repo old et le nouveau SVN dans git repo new
  2. Récupérer old dans new
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase new au-dessus de old (devrait réussir, car les arbres à la racine de new et la pointe de old sont identiques)
    • git checkout master (Suppose que la branche master pointe vers la tête SVN. Ce sera le cas avec un clone propre; sinon, engagez-le avant de commencer.)
    • git rebase --root --onto old
  4. Reconstruisez les métadonnées git-svn de new pour tenir compte du rebase
    • git update-ref --no-deref refs/remotes/git-svn master (ajustez la référence de la télécommande en fonction de la façon dont vous avez cloné, par exemple, cela pourrait être refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info
0
Ben Challenor