2010-11-12 19 views
22

J'ai utilisé git-svn pour créer un miroir git d'un référentiel SVN. La structure à l'intérieur du SVN était un peu hors normes, donc git a créé une branche qui n'a pas de commit commun avec la branche master.git - définition d'un parent de validation sans rebase

 A---B---C topic 

D---E---F---G master 

Je sais que commettras A est basé sur commettras E et je suis positif que j'ai corrigé les problèmes causant git de ne pas reconnaître ce fait (en utilisant filter-branch). Ce que je veux faire est ré-attacher topic à la branche master, la mise en E comme parent A:

 A---B---C topic 
    /
D---E---F---G master 

git-rebase ne semble pas fonctionner pour moi parce que la diff pour commettre A listes la création d'un beaucoup de fichiers qui existent déjà dans master, ce qui entraîne un grand nombre de conflits.
De ma compréhension de git juste le réglage E comme parent de A devrait être suffisant pour résoudre tous les problèmes.
Est-ce possible? Si c'est le cas, comment puis-je le faire?

+0

Une chance de ré-initier le miroir git du svn pointant "branches" vers le bon répertoire? Ou fixer la structure svn en premier? – stefanw

+0

effectivement le repo a utilisé la disposition standard trunk/tags/branches. Cependant la branche que j'essayais de réparer a été créée en copiant seulement un sous-chemin de tronc - devinez qui était un peu trop pour que git-svn manipule. –

+0

rebase a une option 'root'. Utilisez cela avec 'on' et' preserve-merges' si vous en avez besoin. –

Répondre

28

Regardez les greffes (le fichier de greffe se trouve dans .git/info/grafts). Le format est assez simple:

<commit sha1> <parent1 sha1> <parent2 sha1> … <parentN sha1> 

Ceci fait croire à git qu'un commit a des parents différents de ce qu'il a réellement. Utiliser un filtre-branche pour faire des greffes permanentes (de sorte que le fichier peut être supprimé greffes):

git filter-branch --tag-name-filter cat -- --all 

Notez que cette histoire de réécritures du dépôt, ne devrait donc pas être utilisé sur les pensions partagées!


Si vous ne souhaitez que de réécrire l'histoire des commits qui sont greffées sur la branche principale, par exemple, utilisez cette commande:

git filter-branch --tag-name-filter cat -- master.. 
+0

n'utilisez pas de greffes ou de branchement de filtre si vous n'en avez pas besoin. –

+3

Les greffes sont incroyablement utiles si vous en avez besoin, mais comme d'autres fonctionnalités de git, elles doivent être utilisées avant de partager le repo (ou vous devrez demander à tout le monde de reclasser). Comme la réponse le dit, créez simplement le fichier de greffons (hash-of-A, espace, hash-of-E, newline) et utilisez "git filter-branch - tag-nom-filtre-chat" pour réécrire histoire sans changer d'autres données de validation – JodaStephen

+0

@JodaStephen vous devriez ajouter cela à la réponse. Savez-vous s'il est possible de le faire si le référentiel est publié, mais les greffes avec lesquelles vous jouez ne concernent que les nouveaux commits non publiés? – naught101

8

Sur la base de vos schémas (bien que je suis préoccupé par ce que vous entendez par "Je suis assez positif que j'ai corrigé les problèmes provoquant git de ne pas reconnaître ce fait (en utilisant filter-branch)."), vous devriez être capable de faire quelque chose comme ce qui suit.

# checkout A 
git checkout A 

# Reset the branch pointer to E so that E is the parent of the next commit 
# --soft ensures that the index stays the same 
git reset --soft E 

# Remake the commit with the E as the parent, re-using the old commit metadata 
git commit -C [email protected]{1} 

# Rebase the topic branch onto the modified A commit (current HEAD) 
git rebase --onto HEAD A topic 
+0

Fonctionne presque bien, mais le sujet finit par ne pas suivre l'origine/sujet distant après cette opération! –

5

Tout ce que vous avez besoin est ceci:

git rebase --root --onto master^^ topic^^ topic 

l'option racine vous permet d'inclure A.

MISE À JOUR:

Ajoutez l'option --preserve-merges si vous souhaitez conserver la ramification et fusion de la partie que vous rebasez.

+1

Cette commande a parfaitement fonctionné pour moi! – jarvisschultz

+0

Cela fonctionne très bien si vous avez un historique linéaire, s'il a des commits de fusion, vous devez utiliser '--preserve-merges', et vous devez résoudre les conflits de fusion manuellement. – Flimm

+0

Oui. Je vais mettre à jour la réponse. Une autre fois que j'ai répondu à la même question, j'ai inclus cette option. –