J'ai besoin de fusionner deux référentiels Git dans un troisième référentiel flambant neuf. J'ai trouvé de nombreuses descriptions de la façon de procéder en utilisant une fusion de sous-arborescence (par exemple la réponse de Jakub Narębski sur Comment fusionner deux référentiels Git? ) Et en suivant ces instructions fonctionne principalement, sauf que lorsque je valide la sous-arborescence, fusionne tous les fichiers des anciens référentiels sont enregistrés en tant que nouveaux fichiers ajoutés. Je peux voir l'historique des validations des anciens référentiels quand je le fais git log
, mais si je le fais, git log <file>
il ne montre qu'une seule validation pour ce fichier - la fusion des sous-arbres. À en juger par les commentaires sur la réponse ci-dessus, je ne suis pas le seul à voir ce problème mais je n'ai trouvé aucune solution publiée pour le résoudre.
Existe-t-il un moyen de fusionner les référentiels et de laisser l'historique des fichiers individuels intact?
la source
Réponses:
Il s'avère que la réponse est beaucoup plus simple si vous essayez simplement de coller deux référentiels ensemble et de faire en sorte que ce soit comme ça tout au long plutôt que de gérer une dépendance externe. Il vous suffit d'ajouter des télécommandes à vos anciens référentiels, de les fusionner avec votre nouveau maître, de déplacer les fichiers et dossiers dans un sous-répertoire, de valider le déplacement et de répéter pour tous les référentiels supplémentaires. Les sous-modules, les fusions de sous-arbres et les rebases sophistiqués sont destinés à résoudre un problème légèrement différent et ne conviennent pas à ce que j'essayais de faire.
Voici un exemple de script Powershell pour coller deux référentiels ensemble:
Évidemment, vous pouvez plutôt fusionner old_b dans old_a (qui devient le nouveau référentiel combiné) si vous préférez le faire - modifier le script en fonction.
Si vous souhaitez également ajouter des branches de fonctionnalités en cours, utilisez ceci:
C'est la seule partie non évidente du processus - ce n'est pas une fusion de sous-arborescence, mais plutôt un argument pour la fusion récursive normale qui indique à Git que nous avons renommé la cible et qui aide Git à tout aligner correctement.
J'ai écrit une explication un peu plus détaillée ici .
la source
git mv
ne fonctionne pas si bien. lorsque vous utilisez ultérieurement ungit log
sur l'un des fichiers déplacés, vous obtenez uniquement la validation du déplacement. toute l'histoire précédente est perdue. c'est parce quegit mv
c'est vraimentgit rm; git add
mais en une seule étape .git log --follow
, ou tous les outils GUI le font automatiquement pour vous. Avec une fusion de sous-arborescence, vous ne pouvez pas obtenir l'historique des fichiers individuels, à ma connaissance, donc cette méthode est meilleure.1
(le numéro un) pourls
et le «œil» capital pourxargs
. Merci pour cette astuce!Voici un moyen qui ne réécrit aucun historique, donc tous les ID de validation resteront valides. Le résultat final est que les fichiers du second dépôt se retrouveront dans un sous-répertoire.
Ajoutez le deuxième dépôt en tant que télécommande:
Assurez-vous d'avoir téléchargé tous les commits de secondrepo:
Créez une branche locale à partir de la deuxième branche du référentiel:
Déplacez tous ses fichiers dans un sous-répertoire:
Fusionnez la deuxième branche dans la branche principale du premier dépôt:
Votre référentiel aura plus d'un commit racine, mais cela ne devrait pas poser de problème.
la source
git remote show secondrepo
)--allow-unrelated-histories
. Voir l'historique de ce message de réponse.Quelques années se sont écoulées et il existe des solutions bien votées mais je veux partager la mienne car elle était un peu différente parce que je voulais fusionner 2 référentiels distants en un nouveau sans supprimer l'historique des référentiels précédents.
Créez un nouveau référentiel dans Github.
Téléchargez le référentiel nouvellement créé et ajoutez l'ancien référentiel distant.
Récupère tous les fichiers de l'ancien référentiel pour créer une nouvelle branche.
Dans la branche principale, effectuez une fusion pour combiner l'ancien référentiel avec le nouveau créé.
Créez un nouveau dossier pour stocker tout le nouveau contenu créé qui a été ajouté à partir de OldRepo et déplacez ses fichiers dans ce nouveau dossier.
Enfin, vous pouvez télécharger les fichiers à partir des dépôts combinés et supprimer en toute sécurité OldRepo de GitHub.
J'espère que cela peut être utile pour toute personne confrontée à la fusion de référentiels distants.
la source
git remote rm OldRepo
.s'il vous plaît jeter un oeil à l'aide
pour relier deux histoires au début de leur vie.
Si vous avez des chemins qui se chevauchent, corrigez-les avec
lorsque vous utilisez le journal, assurez-vous de "trouver des copies plus
de cette façon, vous trouverez tous les mouvements de fichiers dans le chemin.
la source
J'ai transformé la solution de @Flimm ceci en un
git alias
comme ça (ajouté à mon~/.gitconfig
):la source
$GIT_PREFIX
?Cette fonction clone le repo distant dans le répertoire repo local:
Comment utiliser:
Remarquer. Ce script peut réécrire les validations, mais enregistrera tous les auteurs et toutes les dates, cela signifie que les nouvelles validations auront un autre hachage, et si vous essayez de pousser les modifications sur le serveur distant, il ne pourra le faire qu'avec la touche de force, il réécrira également les validations sur le serveur. Veuillez donc faire des sauvegardes avant de lancer.
Profit!
la source
git filter-branch --index-filter
au travail. En général, je reçois un message d'erreur indiquant que le fichier d'index .new n'existe pas. Cela vous rappelle-t-il quelque chose?git-add-repo.sh
avec la fonction ci-dessus, à la fin du fichier mettez cette lignegit-add-repo "$@"
. Après cela, vous pouvez l'utiliser à partir de zsh commecd current/git/package
etbash path/to/git-add-repo.sh https://github.com/example/example dir/to/save
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
échoue parfois, vous devez donc ajouter unif test
.Suivez les étapes pour intégrer un référentiel dans un autre référentiel, en ayant un seul historique git en fusionnant les deux historiques git.
my/new/subdir
(3 occurrences) par la structure de répertoires où vous souhaitez avoir le dépôt enfant.Si vous vérifiez le journal git dans le référentiel parent maintenant, il devrait fusionner les validations du référentiel enfant. Vous pouvez également voir la balise indiquant la source de validation.
L'article ci-dessous m'a aidé à intégrer un référentiel dans un autre référentiel, à avoir un seul historique git en fusionnant les deux historiques git.
http://ericlathrop.com/2014/01/combining-git-repositories/
J'espère que cela t'aides. Codage heureux!
la source
git filter-branch --prune-empty --tree-filter ' if [ ! -e my/new/subdir ]; then mkdir -p my/new/subdir; git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files my/new/subdir; fi'
Dites que vous souhaitez fusionner dépôt
a
dansb
(je suppose qu'ils sont situés à côté de l'autre):Si vous souhaitez placer
a
dans un sous-répertoire, procédez comme suit avant les commandes ci-dessus:Pour cela, vous devez
git-filter-repo
installer (filter-branch
est déconseillé ).Un exemple de fusion de 2 grands référentiels, en plaçant l'un d'entre eux dans un sous-répertoire: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
Plus d'informations ici .
la source