Comment concaténer deux histoires git?

J'ai deux repositorys git qui sont liés tangentiellement. A savoir, le contenu de l'un était un prédécesseur de l'autre. Je voudrais d'une manière ou d'une autre préfixer l'histoire complète du repository A au dépositaire B, de sorte que l'astuce de A serait un parent du tout premier set de modifications du référentiel B? Les histoires dans les deux sont assez linéaires.

Est-ce possible?

Solutions Collecting From Web of "Comment concaténer deux histoires git?"

Vous pourriez essayer d'utiliser le file de greffe ( .git/info/grafts ) où vous pourriez écraser la parenté d'un commit (comme le premier de projectB ayant pour parent le dernier de projectA )

Voir aussi "A quoi servent les files .git / info / greffes? " Et " Comment append le passé à un repository git? " Pour plus d'informations sur cette manipulation.


skalee commente l'article " Git: Grefting repositories " (de l'user de SO Ben Straub ) pour un exemple concret.

Maintenant ce que nous voulons faire est de changer le premier commit dans le " nuevo " repo (" New commit #1 ") pour que son parent soit le dernier commit dans le "vieux" repo ("Old # 3"). Il est time pour du vaudou:

 git fetch ../old master:ancient_history 

Git vous permet d'aller chercher dans n'importe quel autre repository git, que ce repo y soit lié ou non! Brillant! Cela nous laisse avec ceci:

entrez la description de l'image ici

Notez comment nous avons renommé l'ancienne twig maître en ancient_history. Si nous ne l'avions pas fait, git aurait essayé de merge les deux, et probablement abandonné dans le dégoût.

Maintenant, nous avons toujours un problème.
Les deux trees ne sont pas connectés, et en fait, un pull git n'obtiendra même pas la twig ancient_history. Nous avons besoin d'un moyen de faire un lien entre les deux.

Git a une fonction appelée greffe, qui fausse fondamentalement un lien parent entre deux commits.
Pour en faire un, il suffit d'insert une ligne dans le .git/info/grafts dans ce format:

 [ref] [parent] 

Les deux doivent être le hachage complet des commits en question. Alors trouvons-les:

 $ git rev-list master | tail -n 1 d7737bffdad86dc05bbade271a9c16f8f912d3c6 $ git rev-parse ancient_history 463d0401a3f34bd381c456c6166e514564289ab2 $ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \ 463d0401a3f34bd381c456c6166e514564289ab2 \ > .git/info/grafts 

(en une ligne, comme suggéré par ssokolow )

 echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts 

Là. Maintenant, notre histoire ressemble à ceci:

entrez la description de l'image ici

Le clonage de ce repo entraîne ceci:

entrez la description de l'image ici

Woops. Il s'avère que les greffes ne sont efficaces que pour le référentiel local. Nous pouvons résoudre ce problème avec une application judicieuse de git fast-import :

 $ git fast-export --all > ../export $ mkdir ../nuevo-complete $ cd ../nuevo-complete $ git init $ git fast-import < ../export git-fast-import statistics: [...] 

(en une ligne, comme suggéré par ssokolow )

 git filter-branch $(git rev-parse ancient_history)..HEAD 

Ceci convertit effectivement notre lien d'histoire "faux" en un lien réel.
Tous les ingénieurs devront re-cloner à partir de ce nouveau référentiel, puisque les hachages seront tous différents, mais c'est un petit prix à payer pour aucun time d'arrêt et un historique complet.

entrez la description de l'image ici

Comme Qix commentaires ci – dessous :

fast-import semble fast-import simplement les informations git, mais ne vérifie rien.
git init vous met à l'origine sur master, vous avez donc besoin d'une git reset --hard HEAD pour vérifier les files après l' fast-import .