2016-11-17 1 views
0

Je travaille sur la restauration de l'historique d'une base de code. J'ai récupéré commits lost at the root de mon repo git, et j'ai maintenant découvert une nouvelle complication.Restaurer l'historique des repo divergents, puis convergents

Une grande partie de code a été divisé en une base de code séparé pendant un certain temps ... puis a fusionné avant.

Main repo: A -- B -- C -- D -- E 
        |  ^
Code moved:  |   | 
        V   | 
Other repo:  X -- Y -- Z 

Lorsque la scission (et fusion) a eu lieu, les fichiers ont été simplement copiés dans le repo cible, et l'histoire a été perdue. Pour compliquer davantage les choses, les fichiers ont été légèrement modifiés sur chaque copie avant la validation, il est donc probable que j'aurai besoin d'un commit supplémentaire pour ces changements.

Cela me conduit à deux questions:

Est-il possible de remplacer commettre D (qui copie les fichiers en arrière) avec la branche inférieure (X-Y-Z)? (Ceci est ma priorité.)

Si c'est possible, sera-t-il également possible de restaurer l'historique des fichiers créés au commit X?

Il y a environ 300 validations sur le "autre" repo, et environ 5000 sur le repo "principal" à partir de D.

Je suppose que git-rebase est probablement nécessaire, mais idéalement, je voudrais utiliser git-filter-branch de sorte que je n'ai pas à résoudre manuellement les conflits de fusion historiques.

Répondre

1

Vous pouvez configurer quelques git replace -ments pour modifier/coller chirurgicalement l'historique, sans modifier le contenu de tous les validations existantes. Ensuite, faites la branche de filtre comme nous l'avons déjà discuté ailleurs, pour que ces greffons de remplacement deviennent permanents. Parce que git replace vous permet de remplacer dans un objet de remplacement partout où Git "voit" normalement l'original, et parce que les commits ont des ID de validation parents, vous pouvez remplacer un seul commit par une chaîne de plusieurs validations. Par exemple, si commettre X est "mauvais" d'une manière bien définie:

...--o--P--X--Q--o--... 

nous construire une nouvelle séquence de "bonne" engage G ... G n:

...--o--P--X--Q--o--... 
     \ 
      G1--G2--...--Gn 

(où G 1 parent de commit ID est P, qui est notre mauvaise X mère Engageons, si X besoins, ou mérite, plusieurs parents, nous pouvons mettre toutes les personnes en bonne commi t G). Ensuite, nous demandons Git « remplacer » X avec G n, de sorte que traversal ressemble à ceci:

...--o--P--X- [replaced] -Q--o--... 
     \    /
      G1--G2--...--Gn 

Une fois filtrée, X disparaît entièrement, avec commits Q, puis copiés sur leurs nouvelles copies dans l'habituel mode filtre-branche.

Pour construire le « bon » engage, vous pouvez littéralement git checkout -b tempbranch <P> puis commencer à faire les commits, mais si vous devez définir plusieurs parents c'est un peu plus compliqué (vous pouvez utiliser git commit-tree au lieu de git commit ordinaire, ou de tricher par créer .git/MERGE_HEAD avec les hachages supplémentaires restants). Vous voudrez peut-être antidater les nouveaux "bons" commits, et/ou définir des auteurs arbitraires (git commit a des commutateurs de ligne de commande pour ceux-ci, git commit-tree vous oblige à utiliser les variables env magiques).