212 votes

Combiner plusieurs dépôts git

Disons que j'ai une configuration qui ressemble à quelque chose comme

phd/code/
phd/figures/
phd/thesis/

Pour des raisons historiques, ils ont tous leurs propres dépôts git. Mais j'aimerais les combiner en un seul pour simplifier un peu les choses. Par exemple, à l'heure actuelle, je pourrais faire deux séries de modifications et avoir à faire quelque chose comme

cd phd/code
git commit 
cd ../figures
git commit

Ce serait (maintenant) bien de juste faire le spectacle.

cd phd
git commit

Il semble qu'il y ait plusieurs façons de faire cela en utilisant des submodules ou en tirant de mes sous-dépôts, mais c'est un peu plus complexe que ce que je recherche. Au minimum, je me contenterais de

cd phd
git init
git add [[everything that's already in my other repositories]]

mais ça ne ressemble pas à une phrase toute faite. Y a-t-il quelque chose dans git qui peut m'aider ?

0 votes

Considérez également cette excellente approche : stackoverflow.com/questions/1425892/

0 votes

Pensez aussi à : saintgimp.org/2013/01/22/…

0 votes

El join-git-repos.py script fait un bon travail si vous avez des dépôts séparés, chacun avec des branches maîtres que vous voulez combiner.

155voto

MiniQuark Points 8927

Voici une solution que j'ai donnée aquí :

  1. Faites d'abord une sauvegarde complète de votre répertoire phd : Je ne veux pas être tenu responsable de la perte de vos années de dur labeur ! ;-)

    $ cp -r phd phd-backup
  2. Déplacez le contenu de phd/code a phd/code/code et corrige l'historique pour qu'il ait l'air d'avoir toujours été là (ceci utilise la fonction git filtre-branche commande) :

    $ cd phd/code
    $ git filter-branch --index-filter \
        'git ls-files -s | sed "s#\t#&code/#" |
         GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
         git update-index --index-info &&
         mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
  3. Idem pour le contenu de phd/figures y phd/thesis (il suffit de remplacer code con figures y thesis ).

    Maintenant, votre structure de répertoire devrait ressembler à ceci :

    phd
      |_code
      |    |_.git
      |    |_code
      |         |_(your code...)
      |_figures
      |    |_.git
      |    |_figures
      |         |_(your figures...)
      |_thesis
           |_.git
           |_thesis
                |_(your thesis...)
  4. Ensuite, créez un dépôt git dans le répertoire Root, mettez-y tout et supprimez les anciens dépôts :

    $ cd phd
    $ git init
    
    $ git pull code
    $ rm -rf code/code
    $ rm -rf code/.git
    
    $ git pull figures --allow-unrelated-histories
    $ rm -rf figures/figures
    $ rm -rf figures/.git
    
    $ git pull thesis --allow-unrelated-histories
    $ rm -rf thesis/thesis
    $ rm -rf thesis/.git

    Enfin, vous devriez maintenant avoir ce que vous vouliez :

    phd
      |_.git
      |_code
      |    |_(your code...)
      |_figures
      |    |_(your figures...)
      |_thesis
           |_(your thesis...)

Le bon côté de cette procédure est qu'elle laisse non-versionné fichiers et répertoires en place.

J'espère que cela vous aidera.


Un seul mot d'avertissement cependant : si votre code a déjà un code un sous-répertoire ou un fichier, les choses risquent de mal tourner (idem pour figures y thesis bien sûr). Si c'est le cas, renommez simplement ce répertoire ou ce fichier avant de suivre toute cette procédure :

$ cd phd/code
$ git mv code code-repository-migration
$ git commit -m "preparing the code directory for migration"

Et quand la procédure est terminée, ajoutez cette dernière étape :

$ cd phd
$ git mv code/code-repository-migration code/code
$ git commit -m "final step for code directory migration"

Bien sûr, si le code le sous-répertoire ou le fichier n'est pas versionné, utilisez simplement mv au lieu de git mv et oubliez le git commit s.

13 votes

Merci pour cet extrait - il a fait exactement ce dont j'avais besoin (une fois que j'ai pris en compte le fait que Mac OS X sed ne traite pas " \t " (j'ai dû utiliser ^V^I à la place).

0 votes

Oui, c'est exactement le genre d'approche que j'espérais que quelqu'un pourrait expliquer !

6 votes

Au début, je n'arrivais pas à le faire fonctionner et j'ai fini par trouver la solution au problème sur un autre vieux forum de discussion. Sur la dernière ligne, j'ai dû mettre des guillemets autour des noms de fichiers comme ceci : mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD et puis ça a bien marché !

78voto

Aristotle Pagaltzis Points 43253

git-stitch-repo traitera la sortie de git-fast-export --all --date-order sur les dépôts git indiqués sur la ligne de commande, et créer un flux adapté pour git-fast-import qui créera un nouveau dépôt contenant tous les commits dans un nouvel arbre de commit qui respecte l'historique de tous les dépôts sources.

0 votes

Ah, merci ! J'espérais qu'il y aurait une commande pour faire ça, mais bon, c'est parfois difficile de connaître toute l'étendue des fonctionnalités de git :)

33 votes

Euh, c'est un outil tiers, qui ne fait pas partie de git :-)

1 votes

En effet, c'est maintenant que tu me le dis :) Oh bien, je suppose que je devais apprendre à installer des paquets CPAN un jour

20voto

Peut-être, simplement (de la même manière que la réponse précédente, mais en utilisant des commandes plus simples) faire dans chacun des anciens dépôts séparés un commit qui déplace le contenu dans un sous-répertoire convenablement nommé, par exemple :

$ cd phd/code
$ mkdir code
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean:
$ git mv * code/
$ git commit -m "preparing the code directory for migration"

et ensuite fusionner les trois dépôts séparés en un nouveau, en faisant quelque chose comme :

$ cd ../..
$ mkdir phd.all
$ cd phd.all
$ git init
$ git pull ../phd/code
...

Ensuite, vous sauvegarderez vos historiques, mais vous continuerez avec un seul repo.

0 votes

C'est ok, mais si vous fusionnez un repo dans un autre (i.e. phd était un repo existant non vide) alors si phd avait des dossiers avec les mêmes noms que les sous-dossiers dans le répertoire code, vous aurez des problèmes car 'git pull ../phd/code' tire tous les commits avec les chemins originaux et seulement à la fin il applique le commit mv.

1 votes

@Tymek : mais cela fonctionnera toujours dans cette situation, sans problèmes. La chose qui ne sera pas agréable est que les chemins dans l'historique ne seront pas "corrects" (correspondent aux nouveaux chemins).

20voto

Leif Gruenwoldt Points 3583

Vous pouvez essayer le stratégie de fusion de sous-arbres . Il vous permettra de fusionner la repo B avec la repo A. L'avantage par rapport à git-filter-branch c'est qu'il ne nécessite pas de réécrire l'historique du repo A (casser les sommes SHA1).

0 votes

Le lien ne fonctionne pas et cela ne préserverait pas l'histoire, n'est-ce pas ?

3 votes

@Tymek (Désolé, certaines parties de kernel.org sont toujours hors service après la faille de sécurité). Cela casse les SHA1's du repo entrant B. Mais A reste intact.

2 votes

Voici un miroir de ce document pour le moment. ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/howto/

9voto

Snafu Points 104

La solution git-filter-branch fonctionne bien, mais notez que si votre repo git provient d'une importation SVN, elle peut échouer avec un message du type :

Rewrite 422a38a0e9d2c61098b98e6c56213ac83b7bacc2 (1/42)mv: cannot stat `/home/.../wikis/nodows/.git-rewrite/t/../index.new': No such file or directory

Dans ce cas, vous devez exclure la révision initiale de la branche de filtrage, c'est-à-dire modifier l'attribut HEAD à la fin pour [SHA of 2nd revision]..HEAD - voir :

http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html

2 votes

Merci. Je me demandais pourquoi cela ne fonctionnait pas ! Le repo provient en effet de SVN.

1 votes

Même erreur quand je fais ça. J'ai perdu espoir. De plus, le lien est maintenant cassé.

0 votes

Pourriez-vous préciser ce que vous entendez par "changer l'en-tête en ...", mon repo provient d'une importation SVN et je suis confronté exactement à ce problème, j'apprécierais beaucoup votre aide !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X