J'ai un référentiel Git dans un dossier appelé XXX et j'ai un deuxième référentiel Git appelé YYY .
Je souhaite importer le référentiel XXX dans le référentiel YYY en tant que sous-répertoire nommé ZZZ et ajouter tout l' historique des modifications de XXX à YYY .
Structure des dossiers avant:
├── XXX
│ ├── .git
│ └── (project files)
└── YYY
├── .git
└── (project files)
Structure des dossiers après:
YYY
├── .git <-- This now contains the change history from XXX
├── ZZZ <-- This was originally XXX
│ └── (project files)
└── (project files)
Cela peut-il être fait ou dois-je recourir à des sous-modules?
Réponses:
La façon la plus simple serait probablement de tirer le truc XXX dans une branche en YYY puis de le fusionner dans master:
En AAAA :
En fait, je viens d'essayer cela avec quelques-uns de mes repos et cela fonctionne. Contrairement à la réponse de Jörg, cela ne vous permettra pas de continuer à utiliser l'autre dépôt, mais je ne pense pas que vous l'ayez spécifié de toute façon.
Remarque: Puisque cela a été écrit à l'origine en 2009, git a ajouté la fusion de sous-arborescence mentionnée dans la réponse ci-dessous. J'utiliserais probablement cette méthode aujourd'hui, même si bien sûr cette méthode fonctionne toujours.
la source
git mv $(ls|grep -v <your foldername>) <your foldername>/
cela copiera tous les fichiers et dossiers dans votre nouveau dossierSi vous souhaitez conserver l'historique de validation exact du deuxième référentiel et donc conserver la possibilité de fusionner facilement les modifications en amont à l'avenir, voici la méthode que vous souhaitez. Il en résulte un historique non modifié de la sous-arborescence importée dans votre référentiel plus un commit de fusion pour déplacer le référentiel fusionné vers le sous-répertoire.
Vous pouvez suivre les modifications en amont comme suit:
Git détermine par lui-même où se trouvent les racines avant d'effectuer la fusion, vous n'avez donc pas besoin de spécifier le préfixe lors des fusions suivantes.
L' inconvénient est que dans l'historique fusionné, les fichiers ne sont pas préfixés (pas dans un sous-répertoire). En conséquence
git log ZZZ/a
, vous montrera toutes les modifications (le cas échéant), sauf celles de l'historique fusionné. Tu peux faire:mais cela ne montrera pas les changements autres que dans l'historique fusionné.
En d'autres termes, si vous ne changez pas
ZZZ
les fichiers dans le référentielXXX
, vous devez spécifier--follow
et un chemin non préfixé. Si vous les modifiez dans les deux référentiels, vous disposez de 2 commandes, dont aucune ne montre toutes les modifications.Versions Git antérieures à 2.9 : vous n'avez pas besoin de passer l'
--allow-unrelated-histories
option àgit merge
.La méthode de l'autre réponse qui utilise
read-tree
et ignore l'merge -s ours
étape n'est en fait pas différente de la copie des fichiers avec cp et de la validation du résultat.La source d'origine était tirée de l'article d'aide de "Subtree Merge" de github . Et un autre lien utile .
la source
git log
sur l'un des fichiers que j'ai récupérés, je vois juste le commit de fusion unique et rien de sa vie précédente dans l'autre dépôt? Git 1.8.0git log -- myfile
au lieu degit log -- rack/myfile
--allow-unrelated-histories
lors de la fusion.git-subtree
est un script conçu exactement pour ce cas d'utilisation de fusion de plusieurs référentiels en un seul tout en préservant l'historique (et / ou le fractionnement de l'historique des sous-arbres, bien que cela semble être sans rapport avec cette question). Il est distribué dans le cadre de l'arbre git depuis la version 1.7.11 .Pour fusionner un référentiel
<repo>
à la révision en<rev>
tant que sous<prefix>
- répertoire , utilisezgit subtree add
comme suit:git-subtree implémente la stratégie de fusion des sous-arbres de manière plus conviviale.
Pour votre cas, dans le référentiel YYY, vous exécuteriez:
L' inconvénient est que dans l'historique fusionné, les fichiers ne sont pas préfixés (pas dans un sous-répertoire). En conséquence
git log ZZZ/a
, vous montrera toutes les modifications (le cas échéant), sauf celles de l'historique fusionné. Tu peux faire:mais cela ne montrera pas les changements autres que dans l'historique fusionné.
En d'autres termes, si vous ne changez pas
ZZZ
les fichiers dans le référentielXXX
, vous devez spécifier--follow
et un chemin non préfixé. Si vous les modifiez dans les deux référentiels, vous disposez de 2 commandes, dont aucune ne montre toutes les modifications.Plus d'informations ici .
la source
git subtree add -P name-of-desired-prefix ~/location/of/git/repo-without-.git branch-name
Il existe un exemple bien connu de cela dans le référentiel Git lui-même, qui est collectivement connu dans la communauté Git comme " la fusion la plus cool jamais " (après la ligne d'objet Linus Torvalds utilisée dans l'e-mail à la liste de diffusion Git qui décrit cela fusionner). Dans ce cas, l'
gitk
interface graphique Git qui fait maintenant partie de Git proprement dit, était en fait un projet distinct. Linus a réussi à fusionner ce référentiel dans le référentiel Git d'une manière quigit pull
éditées.L'e-mail contient les étapes nécessaires pour se reproduire, mais ce n'est pas pour les âmes sensibles: premièrement, Linus a écrit Git, donc il en sait probablement un peu plus à ce sujet que vous ou moi, et deuxièmement, c'était il y a presque 5 ans et Git s'est considérablement amélioré depuis lors, alors c'est peut-être maintenant beaucoup plus facile.
En particulier, je suppose que de nos jours, on utiliserait un sous-module gitk, dans ce cas spécifique.
la source
git-subtree
outil tiers qui peut vous aider avec ceci: github.com/apenwarr/git-subtreesubtree
stratégie de fusion, en particulier conjointement avec l'git-subtree
outil, est une alternative intéressante, voire supérieure aux sous-modules.Le moyen le plus simple est d'utiliser git format-patch.
Supposons que nous ayons 2 référentiels git foo et bar .
foo contient:
la barre contient:
et nous voulons finir avec foo contenant l' historique de la barre et ces fichiers:
Donc, pour ce faire:
Et si nous voulons réécrire toutes les validations de messages à partir de la barre, nous pouvons le faire, par exemple sous Linux:
Cela ajoutera "[bar]" au début de chaque message de validation.
la source
git am
échouera probablement.[ ]
le message de validation. Vous devez donc utiliser un marqueur différent de celui de[bar]
Cette fonction clonera le dépôt distant dans le répertoire de dépôt local, après la fusion de tous les validations seront enregistrées,
git log
affichera les validations d'origine et les chemins d'accès appropriés:Comment utiliser:
Si vous apportez quelques modifications, vous pouvez même déplacer les fichiers / répertoires du référentiel fusionné dans différents chemins, par exemple:
Avis
Paths remplace via
sed
, alors assurez-vous qu'il s'est déplacé dans les chemins appropriés après la fusion.Le
--allow-unrelated-histories
paramètre n'existe que depuis git> = 2.9.la source
gnu-sed
pour que lagit-add-repo
fonction fonctionne. Merci encore Andrey!Sur la base de cet article , l'utilisation de sous-arbre est ce qui a fonctionné pour moi et seul l'historique applicable a été transféré. Publier ici au cas où quelqu'un aurait besoin des étapes (assurez-vous de remplacer les espaces réservés par des valeurs qui vous concernent):
dans votre sous-dossier de partage de référentiel source dans une nouvelle branche
git subtree split --prefix=<source-path-to-merge> -b subtree-split-result
dans votre référentiel de destination fusionner dans la branche de résultat fractionnée
vérifier vos modifications et vous engager
N'oubliez pas
Nettoyer en supprimant la
subtree-split-result
branchegit branch -D subtree-split-result
Supprimez la télécommande que vous avez ajoutée pour récupérer les données du référentiel source
git remote rm merge-source-repo
la source
Ajouter une autre réponse car je pense que c'est un peu plus simple. Une extraction de repo_dest est effectuée dans repo_to_import puis une URL push --set-upstream: repo_dest master est effectuée.
Cette méthode a fonctionné pour moi en important plusieurs dépôts plus petits dans un plus grand.
Comment importer: repo1_to_import vers repo_dest
Renommez ou déplacez les fichiers et les répertoires dans la position souhaitée dans le référentiel d'origine avant de procéder à l'importation. par exemple
La méthode décrite au lien suivant a inspiré cette réponse. Je l'ai aimé car cela semblait plus simple. Mais méfiez-vous! Il y a des dragons! https://help.github.com/articles/importing-an-external-git-repository
git push --mirror url:repo_dest
pousse votre historique et état de dépôt local à distance (url: repo_dest). MAIS il supprime l'ancien historique et l'état de la télécommande. Le plaisir s'ensuit! : -Ela source
Je voulais importer uniquement certains fichiers de l'autre référentiel (XXX) dans mon cas. Le sous-arbre était trop compliqué pour moi et les autres solutions ne fonctionnaient pas. C'est ce que j'ai fait:
Cela vous donne une liste séparée par des espaces de toutes les validations qui affectent les fichiers que je voulais importer (ZZZ) dans l'ordre inverse (vous devrez peut-être ajouter --follow pour capturer les renommages également). Je suis ensuite allé dans le référentiel cible (YYY), j'ai ajouté l'autre référentiel (XXX) en tant que distant, j'ai fait une recherche et enfin:
qui ajoute tous les commits à votre branche, vous aurez donc tous les fichiers avec leur historique et pourrez faire ce que vous voudrez avec eux comme s'ils avaient toujours été dans ce référentiel.
la source
Voir l' exemple de base dans cet article et envisagez un tel mappage sur les référentiels:
A
<->YYY
,B
<->XXX
Après toutes les activités décrites dans ce chapitre (après la fusion), supprimez la branche
B-master
:Ensuite, appuyez sur les modifications.
Ça marche pour moi.
la source
J'étais dans une situation où je cherchais
-s theirs
mais bien sûr, cette stratégie n'existe pas. Mon histoire était que j'avais bifurqué un projet sur GitHub, et maintenant pour une raison quelconque, ma section localemaster
ne pouvait pas être fusionnéeupstream/master
même si je n'avais apporté aucune modification locale à cette branche. (Je ne sais vraiment pas ce qui s'est passé là-bas - je suppose que l'amont avait fait de grosses poussées en coulisse, peut-être?)J'ai fini par faire
Alors maintenant, my
master
est à nouveau synchronisé avecupstream/master
(et vous pouvez répéter ce qui précède pour toute autre branche que vous souhaitez également synchroniser de la même manière).la source
git reset --hard upstream/master
sur votremaster
branche locale ferait le travail. De cette façon, vous ne perdez pas le conflg de branche locale - des choses comme l'amont par défaut.Je peux suggérer une autre solution (alternative aux sous-modules git ) pour votre problème - outil gil (liens git)
Il permet de décrire et de gérer les dépendances complexes des référentiels git.
Il fournit également une solution au problème de dépendance des sous-modules récursifs git .
Considérez que vous avez les dépendances de projet suivantes: exemple de graphique de dépendance de référentiel git
Ensuite, vous pouvez définir un
.gitlinks
fichier avec la description de la relation des référentiels:Chaque ligne décrit le lien git dans le format suivant:
Enfin, vous devez mettre à jour votre référentiel racine:
En conséquence, vous clonerez tous les projets requis et les lierez les uns aux autres de manière appropriée.
Si vous souhaitez valider toutes les modifications dans un référentiel avec toutes les modifications dans les référentiels liés aux enfants, vous pouvez le faire avec une seule commande:
Les commandes Pull, Push fonctionnent de la même manière:
L'outil Gil (liens git) prend en charge les commandes suivantes:
En savoir plus sur le problème de dépendance des sous-modules récursifs git .
la source
Permettez-moi d'utiliser des noms
a
(à la place deXXX
etZZZ
) etb
(à la place deYYY
), car cela rend la description un peu plus facile à lire.Dites que vous souhaitez fusionner dépôt
a
dansb
(je suppose qu'ils sont situés à côté de l'autre):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
Je ne connais pas de moyen facile de le faire. Vous POUVEZ faire ceci:
Je peux éditer avec des détails si cela semble attrayant.
la source
Je pense que vous pouvez le faire en utilisant «git mv» et «git pull».
Je suis un bon git noob - alors soyez prudent avec votre référentiel principal - mais je viens de l'essayer dans un répertoire temporaire et cela semble fonctionner.
Tout d'abord - renommez la structure de XXX pour qu'elle corresponde à ce que vous voulez qu'elle apparaisse lorsqu'elle se trouve dans YYY:
Maintenant, XXX ressemble à ceci:
Utilisez maintenant 'git pull' pour récupérer les modifications:
Maintenant, YYY ressemble à ceci:
la source