Comment informer git-svn d'une branche distante créée après avoir récupéré le dépôt?

194

J'utilise git-svnpour travailler avec le référentiel Subversion central de mon entreprise. Nous avons récemment créé une nouvelle branche de fonctionnalités dans le dépôt central.

Comment en parler à Git? Lorsque j'exécute, git branch -rje ne peux voir que les branches qui existaient lorsque j'ai exécuté fetchle dépôt Subversion pour initialiser mon dépôt Git?

Hank Gay
la source
Des réponses d'ici: stackoverflow.com/questions/13376917/ ... pourraient également être utiles.
Tomasz Gandor le

Réponses:

296

Vous pouvez ajouter manuellement la branche distante,

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
la source
3
il suffit d'ajouter ce lien vers la documentation comme référence kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
Depuis .git / config, il est assez facile de comprendre comment les branches distantes peuvent être configurées à partir de référentiels uniques / multiples.
Mikael Lepistö
6
Si je pouvais voter huit fois, je le ferais. Enfin, un moyen d'ajouter une branche svn qui est ajoutée dans un emplacement non standard!
Tim Keating
7
J'arrive fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.à l'étape de paiement git.
phpguru
17
@phpguru Essayez de supprimer l'indicateur d'option -t pour qu'il devienne 'git checkout -b local-newbranch newbranch' n'oubliez pas d'inclure le préfixe de la télécommande à newbranch (ex. origin / newbranch).
mj1531
97

Si vous souhaitez suivre TOUTES les branches svn distantes, la solution est aussi simple que:

git svn fetch

Cela récupérera TOUTES les branches distantes qui n'ont pas encore été récupérées.

Astuce supplémentaire: si vous avez extrait uniquement le tronc au début, et plus tard vous souhaitez suivre TOUTES les branches, modifiez-le .git/configpour ressembler à ceci et relancez 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/*

Les points clés urldoivent pointer vers la racine du référentiel et les chemins définis dans fetchet branchesdoivent être relatifs à url.

Si vous voulez récupérer uniquement des branches spécifiques au lieu de TOUTES, il y a un bel exemple dans 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/*

Avec les anciennes versions de git-svn, une fois que vous avez spécifié des branches comme celle-ci, vous ne pourrez peut-être pas obtenir de nouvelles branches avec git svn fetch. Une solution de contournement consiste à ajouter plus de fetchlignes, comme ceci:

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

Une autre solution de contournement par @AndyEstes: modifiez .git/svn/.metadataet modifiez la valeur de branches-maxRevou tags-maxReven une révision avant la création de toutes les branches ou balises nouvellement spécifiées. Une fois que vous avez fait cela, exécutez git svn fetchpour suivre la nouvelle branche distante svn.

Janos
la source
1
Si vous avez déjà récupéré la révision à laquelle le branchement svn a été effectué avant de définir ces paramètres, vous voudrez peut-être faire une réinitialisation git svn.
kcm1700
3
Le montage a .git/svn/.metadataété très utile! J'ajoutais des branches supplémentaires dans my .git/config, qui git svn fetchn'ont pas repris - parce que le numéro de révision des métadonnées était "trop ​​avancé". Dans un cas, seul le dernier commit d'une branche a été récupéré. Je me suis débarrassé manuellement de la branche défectueuse (renommée .git/svn/refs/remotes/svn/qa/XYZen .git/svn/refs/remotes/svn/qa/XYZ~, abandonné son existence .git/packed-refs, etc.) ... j'ai choisi un numéro de révision "antérieur" pour les métadonnées ... couru git svn fetchpour enfin obtenir un historique complet avec un graphique correct et connecté.
starlocke
9
CECI DEVRAIT ÊTRE LA RÉPONSE ACCEPTÉE! @janos, vous venez de me sauver des heures de maux de tête! Si jamais tu viens en Inde, je t'emmène prendre une bière!
Roopesh Shenoy
1
Ou: git svn fetch --all.
kenorb
1
Cette réponse est incroyable, car elle répond à environ 7 questions auxquelles je n'ai pas trouvé de réponse, et cela sans écrire un récit de 6 pages.
Droj
53

Il semble que j'en avais juste besoin git svn fetch; d'une manière ou d'une autre, je m'étais convaincu que cela permettrait de récupérer l'intégralité du dépôt au lieu des seuls changements.

Hank Gay
la source
7
@mitjak Pourquoi n'est-ce pas la bonne réponse, si c'est la solution? Je ne comprends pas la subtilité de la réponse.
rholmes
'une solution' peut-être pas 'la solution'
slf
1
@rholmes: Je suis presque sûr que mitjak signifie que c'est la solution à votre problème mais pas la réponse à la question que vous avez posée. (Parce que vous avez posé la mauvaise question; que vous avez mal interprété le problème à l'époque.)
Mike Nelson
Cela fonctionne lorsque la branche existait au moment où vous avez cloné le dépôt svn dans git. Cela ne fonctionnera pas si la branche dans le référentiel svn a été créée par la suite.
Petr Gladkikh
3
Cela fonctionne bien lorsque la branche a été créée après le clone, je le fais tout le temps.
Tim Gautier
15

Peut-être que je l'ai gâché d'une manière ou d'une autre, mais j'ai suivi les instructions de la réponse de vjangus et cela a presque fonctionné. Le seul problème était que newbranch ne semblait pas être ramifié à partir du tronc. Dans gitk, c'était un peu "flottant" tout seul; il n'avait pas d'ancêtre commun avec le tronc.

La solution à cela était:

  1. Trouvez le SHA1 du dernier commit qui s'est produit sur le tronc avant la création de la branche.
  2. Trouvez le SHA1 du premier commit sur la nouvelle branche (le message est probablement "Created new branch, copied from trunk @ 12345" ou quelque chose)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- il ne devrait y avoir aucune sortie. S'il y a une sortie, vous avez peut-être sélectionné les mauvais commits.
  4. git checkout local-newbranchalors git rebase <sha1 from step 1>. Cela rebasera local-newbranchsur le nouvel arbre mais remotes/newbranchsera toujours déconnecté.
  5. Accédez au fichier .git/refs/remotes/newbranchet modifiez-le pour qu'il contienne le SHA1 complet du nouveau commit (sur le rebasé newbranch) qui correspond à l'ancien commit sur lequel il pointe actuellement. (Ou peut-être utiliser git-update-ref refs/remotes/newbranch <new-SHA>. Merci Inger.)
  6. La prochaine fois que vous git svn dcommità newbranch, vous aurez un tas de messages à ce sujet la mise à jour un certain journal. C'est normal je pense.

Je recommande de rester gitk --allouvert tout le temps et de le rafraîchir souvent pour suivre ce que vous faites. Je suis encore un peu nouveau dans git et git svn, alors veuillez suggérer des améliorations à cette méthode.

MatrixFrog
la source
2
Merci, cela semble utile. À propos de 5. probablement 'git-update-ref refs / remotes / newbranch <new-SHA>' est l'option la plus sûre.
entier le
Je viens de réessayer la méthode de vjangus et cela a parfaitement fonctionné. Je vais laisser ça ici de toute façon car cela pourrait être précieux pour quelqu'un ...
MatrixFrog
1
La solution vjangus crée toujours la nouvelle branche déconnectée du tronc. Je suppose que c'est à cause de la façon dont SVN lui-même n'a aucune idée de la façon dont le contenu réel est copié.
bogdan.mustiata
Mon expérience avec un grand dépôt git-svn est que les branches svn sont toujours créées dans git détaché du tronc. Il devrait y avoir un moyen de les connecter, mais je n'ai pas pris le temps de le comprendre. AFAIK, vous ne pouvez pas rebaser la branche git qui est connectée à la branche svn, car cela va gâcher la logique de dcommit. Nous venons d'apprendre à vivre avec.
Spencer
7

Une simplification de la réponse de vjangus:

Si vous utilisez la mise en page standard dans SVN et que vous avez fait le svn init habituel, git-svn s'occupera de la configuration pour vous. Juste:

  1. Rechercher une révision de copie de branche dans SVN
  2. Récupérez cette révision avec git-svn
  3. Créer une nouvelle télécommande de suivi de branche locale

Un exemple. L'URL SVN est svn+ssh://[email protected]/repo. La branche SVN que je recherche est newbranch. La branche locale git (suivi à distance newbranch) sera git-newbranch.

Étape 1: recherchez la révision de la copie de branche

    # svn log - arrêt sur copie svn + ssh: //[email protected]/repo/branches/newbranch | queue -4
    r7802 | quelqu'un | 21/03/2014 18:54:58 +0000 (ven 21 mars 2014) | 1 ligne

    branchement de HEAD à newbranch
    -------------------------------------------------- ----------------------

Le point de branchement dans SVN est donc la révision 7802.

Étape 2: récupérer la révision

    # git svn chercher -r 7802
    Point de branchement possible trouvé: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Parent de branche trouvé: (refs / remotes / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Suivi du parent avec do_switch
    Parent suivi avec succès
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (réfs / télécommandes / newbranch)

git-svn a fait tout le travail et connaît maintenant la télécommande:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / télécommandes / newbranch

Étape 3: Créez votre nouvelle succursale locale en suivant la distante:

    # git checkout -b git-newbranch -t newbranch
    Extraction des fichiers: 100% (413/413), terminé.
    Branchement git-newbranch mis en place pour suivre les références / télécommandes / newbranch locales.
    Passé à une nouvelle branche 'git-newbranch'
Gil Hamilton
la source
Suivre cela m'a finalement permis de comprendre ( show-refc'est inestimable)! Pour toute personne coincée avec un référencement erroné des branches distantes, vous pouvez les supprimer (je devais le faire git branch -d newbranch, puis forcer la suppression du répertoire de référence .git/svn/refs/remotes/newbranch), puis recommencer à l'étape 2 (ci-dessus).
tutuDajuju
5

Je n'ai trouvé aucune documentation sur cette fonctionnalité, mais il semble que la configuration de git svn prend en charge plusieurs entrées de récupération. De cette façon, vous pouvez également ajouter des branches séparément sans avoir besoin d'ajouter une autre entrée de référentiel svn distante à votre configuration ni d'utiliser des caractères génériques pour obtenir toutes les branches de certains répertoires.

Supposons que votre arbre SVN est vraiment méchant d'avoir beaucoup de branches sans aucune logique sur la façon dont elles sont localisées, par exemple avoir des branches et des sous-répertoires contenant plus de branches.

c'est à dire

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

et vous voulez juste choisir à la main certaines des branches à inclure dans votre dépôt git.

Vous pouvez d'abord initialiser votre référentiel avec uniquement le tronc sans aucune branche supplémentaire:

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

Après cela, vous devriez voir la configuration suivante:

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

chaque fois que vous voulez récupérer une nouvelle branche de MyRepo, vous pouvez simplement ajouter de nouvelles entrées de récupération à la configuration en:

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

Ou vous pouvez modifier la même configuration dans .git / config

Pour récupérer les nouvelles branches après les avoir ajoutées à la configuration, exécutez simplement:

git svn fetch -r 10000:HEAD

[Edit] Parfois, il semble nécessaire d'exécuter fetch avec le paramètre --all pour récupérer les branches nouvellement ajoutées:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
la source
4

Au lieu de gérer les bizarreries git-svn, vous pouvez essayer SubGit .

Il faut installer SubGit dans le référentiel Subversion. Après cela, on peut utiliser le workflow git standard au lieu d'utiliser des commandes spéciales git-svn:

  1. Pousser de nouveaux commits:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Récupération des modifications entrantes

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Créer une nouvelle branche:

    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
    

Voir la documentation SubGit pour plus de détails.

vadishev
la source
1
SubGit a l'inconvénient de créer deux dépôts - un svn et un dépôt git "shadow". Cela pourrait être un problème pour d'énormes dépôts SVN ...
Udo
@Udo si le référentiel SVN a quelques projets, on peut en spécifier un seul et le synchroniser avec le référentiel Git. Dans ce cas, il n'est pas nécessaire de convertir tout le référentiel Subversion en Git. Mais si l'on a un énorme projet SVN dans ce référentiel, on peut convertir non pas toute l'histoire de ce référentiel mais l'histoire à partir d'une révision minimale. Cela permet de réduire la taille du référentiel Git traduit.
vadishev du
1
@Udo - toute entreprise qui ne veut pas acheter son serveur de référentiel un disque dur a ses priorités en désordre. Mais la plupart des endroits dotés d'énormes référentiels prennent leurs référentiels assez au sérieux, et les besoins en espace disque pour les référentiels ne sont généralement pas un problème majeur, même pour les entreprises avec des décennies d'histoire et des dizaines de millions de lignes de code et des centaines de milliers de révisions. C'est la forme la plus concrète de ses actifs intellectuels de base et l'espace disque est assez bon marché. Cela pourrait déclencher la nécessité de mettre à niveau un contrôleur RAID, mais même ainsi, le gain de productivité ...
Bob Kerns
@Bob Kerns - Le fait est que SVN et Git "taille sage" et non compatibles. Ce n'est pas une question de stockage sur disque ou plus. Mais vous pouvez travailler avec un énorme référentiel SVN car vous ne devez généralement extraire que quelques fichiers / projets. Mais vous ne pouvez pas cloner un énorme dépôt Git - cela ne se moque pas du moins ;-) Par "énorme", je veux dire plusieurs concerts.
Udo
2

Pour ajouter à la réponse de vjangus, qui m'a aidé, j'ai également trouvé utile d'ajouter des greffes use git pour attacher les branches au tronc au point approprié - permettant à git de voir l'historique et d'effectuer correctement les fusions.

Il s'agit simplement d'ajouter une ligne .git/info/graftsavec les hachages:

<initial branch commit> <parent commit in trunk>

par exemple.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Crédit à http://evan-tech.livejournal.com/255341.html

(J'ajouterais ceci en commentaire, mais je n'ai pas assez de réputation.)

CD Haddon.
la source
0

Si vous ne procédez pas à l'extraction avec une mise en page valide, vous ne pourrez pas récupérer une succursale distante.

C'est ce que je fais:

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

Après cela, vous pouvez basculer vers une branche distante:

git checkout --track -b branch_name branch_name

Ensuite, vous serez automatiquement basculé vers votre agence.

MikeHoss
la source