352 votes

Fusionner deux référentiels Git sans rompre l'historique des fichiers

J'ai besoin de fusionner deux dépôts Git dans une nouvelle marque, troisième dépôt. J'ai trouvé beaucoup de descriptions de la façon de le faire à l'aide d'un sous-arbre de fusion (par exemple Jakub Narębski de réponse sur Comment fusionner deux dépôts git?) et à la suite de ces instructions, l'ensemble fonctionne, sauf que quand je m'engage le sous-arbre de fusionner tous les fichiers de l'ancien dépôts sont enregistrés en tant que nouveaux fichiers ajoutés. Je peux voir de la validation de l'histoire de l'ancien référentiels lorsque je n' git log, mais si je n' git log <file> il ne montre qu'une seule de s'engager pour que le fichier - le sous-arbre de fusion. À en juger par les commentaires sur la réponse ci-dessus, je ne suis pas la seule à le voir dans ce problème, mais j'ai trouvé aucun publiée solutions pour cela.

Est-il possible de faire fusionner les référentiels et les congés individuels de l'historique des fichiers intacts?

390voto

Eric Lee Points 1244

Il s'avère que la réponse est beaucoup plus simple si vous essayez simplement de la colle à deux référentiels ensemble et le faire paraître comme il a été de cette façon tout au long plutôt que de gérer une dépendance externe. Vous avez simplement besoin d'ajouter des télécommandes à votre ancienne repos, de les fusionner pour votre nouveau maître, de déplacer les fichiers et les dossiers dans un sous-répertoire, commettre le déplacer, et répétez l'opération pour tous les autres titres. Submodules, sous-arborescence de la fusion, et de la fantaisie rebases sont destinés à résoudre un problème un peu différent et ne sont pas adaptés pour ce que j'essayais de faire.

Voici un exemple de script Powershell pour coller deux référentiels ensemble:

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
dir > deleteme.txt
git add .
git commit -m "Initial dummy commit"

# Add a remote for and fetch the old repo
git remote add -f old_a <OldA repo URL>

# Merge the files from old_a/master into new/master
git merge old_a/master

# Clean up our dummy file because we don't need it any more
git rm .\deleteme.txt
git commit -m "Clean up initial file"

# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | %{git mv $_.Name old_a}

# Commit the move
git commit -m "Move old_a files into subdir"

# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master
mkdir old_b
dir –exclude old_a,old_b | %{git mv $_.Name old_b}
git commit -m "Move old_b files into subdir"

Bien évidemment, on pourrait à la place de fusion old_b en old_a (qui devient le nouveau combiné repo) si vous préférez le faire – de modifier le script pour l'adapter.

Si vous voulez apporter plus de en progrès branches, procédez comme ceci:

# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress

C'est le seul non-évidente dans le cadre de la procédure, ce n'est pas un sous-arbre de fusion, mais plutôt d'un argument à la normale récursive de fusion qui indique à Git que nous l'avons renommé la cible et qui permet de Git ligne tout en place correctement.

J'ai écrit un peu plus d'explications détaillées ici.

207voto

Flimm Points 8870

Voici une façon qui n'est pas de réécrire l'histoire, de sorte que tous s'engager Id restera valide. Le résultat final est que la deuxième pensions de fichiers dans un sous-répertoire.

  1. Ajouter la deuxième repo distant:

    cd firstgitrepo/
    git remote add secondrepo username@servername:andsoon
    
  2. Assurez-vous que vous avez téléchargé tous les secondrepo s s'engage à:

    git fetch secondrepo
    
  3. Créer une branche locale de la deuxième des pensions de la direction générale:

    git branch branchfromsecondrepo secondrepo/master
    
  4. Déplacer tous les fichiers dans un répertoire:

    git checkout branchfromsecondrepo
    mkdir subdir/
    git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} subdir/
    git commit -m "Moved files to subdir/"
    
  5. Fusionner le deuxième branche dans la première des pensions de la branche master:

    git checkout master
    git merge secondbranch
    

Votre dépôt aura plus qu'une seule racine s'engager, mais qui ne devrait pas poser un problème.

8voto

Adam Dymitruk Points 34999

s'il vous plaît jeter un oeil à l'aide

 git rebase --root --preserve-merges --onto
 

pour relier deux histoires tôt dans leur vie.

Si vous avez des chemins qui se chevauchent, corrigez-les avec

 git filter-branch --index-filter
 

lorsque vous utilisez le journal, assurez-vous de "trouver des copies plus difficiles" avec

 git log -CC
 

De cette façon, vous trouverez tous les mouvements de fichiers dans le chemin.

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