Configuration de git parent pointeur vers un autre parent
Si j'ai un commit dans le passé que les points à l'un des parents, mais je veux changer le parent qu'il indique, comment pourrais-je aller sur le faire?
Vous devez vous connecter pour publier un commentaire.
À l'aide de
git rebase
. C'est le générique de "prendre commit(s) et plop il/sur un autre parent (de base) de la commande" dans Git.Certaines choses à savoir, cependant:
Depuis commettre SHAs impliquer leurs parents, lorsque vous modifiez le parent d'un commit, ses SHA va changer - de même que le SHAs de tous s'engage qui viennent après lui (plus récent) dans la ligne de développement.
Si vous travaillez avec d'autres personnes, et vous avez déjà poussé le commit en question du public à l'endroit où ils ont tiré en modifiant le commit est probablement une Mauvaise Idée™. Cela est dû à #1, et donc la confusion qui en résulte les autres utilisateurs référentiels de rencontre en essayant de comprendre ce qui s'est passé en raison de votre SHAs n'a plus de correspondance de leur vie pour la "même" s'engage. (Voir la "RÉCUPÉRATION DE l'AMONT REBASE" section de la page de manuel pour plus de détails.)
Cela dit, si vous êtes actuellement sur une branche avec certains s'engage à ce que vous souhaitez déplacer vers un nouveau parent, ça ressemble à quelque chose comme ceci:
Qui va se déplacer tout après
<old-parent>
dans la branche à s'asseoir sur le dessus de<new-parent>
à la place.--onto
est utilisé pour! La documentation a toujours été complètement obscur pour moi, même après la lecture de cette réponse!git rebase --onto <new-parent> <old-parent>
m'a tout Dit sur la façon d'utiliserrebase --onto
que tous les autres question et le document que j'ai lu jusqu'à présent échoué.rebase this commit on that one
, ougit rebase --on <new-parent> <commit>
. À l'aide de la vieille mère, ici, ne fait pas de sens pour moi.git rebase <new-parent>
.--onto
et vos vieux parents sont importants si vous êtes à la relocalisation parce que vos amont relocalisée, ou vous décidez de changer de rapport à l'amont, plutôt que de simplement la suite de l'amont vers l'avant.origin
en face, quelque chose comme ceci:git rebase --onto origin/<new_branch> origin/<old_branch>
Si il s'avère que vous avez besoin pour éviter la relocalisation de la subséquente s'engage (par exemple à cause d'une histoire de réécriture serait un comble), vous pouvez utiliser le git remplacez (disponible dans Git 1.6.5 et plus tard).
Avec le dessus de remplacement établie, les demandes de l'objet B est en fait le retour de l'objet C. Le contenu de C sont exactement les mêmes que le contenu de B, sauf pour le premier parent (même les parents (sauf pour le premier), même arbre, le même message de commit).
Remplacements sont actives par défaut, mais peuvent être activés à l'aide de la
--no-replace-objects
option pour git (avant le nom de la commande) ou par la définition de laGIT_NO_REPLACE_OBJECTS
variable d'environnement. Les remplacements peuvent être partagés en poussantrefs/replace/*
(en plus de la normalerefs/heads/*
) .Si vous n'aimez pas la commettre-munging (avec sed ci-dessus), vous pouvez créer votre remplacement valider à l'aide de niveau supérieur commandes:
La grande différence est que cette séquence ne pas propager les nouveaux parents si B est une fusion de commettre.
refs/replace/
ref hiérarchie. Si vous avez juste besoin de le faire qu'une fois, alors vous pouvez fairegit push yourremote 'refs/replace/*'
dans le référentiel source, etgit fetch yourremote 'refs/replace/*:refs/replace/*'
dans la destination des référentiels. Si vous avez besoin de le faire à plusieurs reprises, vous pouvez ajouter ces refspecs à unremote.yourremote.push
variable de config (dans le référentiel source) et unremote.yourremote.fetch
variable de config (dans la destination des référentiels).git replace --grafts
. Vous ne savez pas quand ce a été ajouté, mais son but est de créer un remplacement est le même que commit B, mais avec les parents.Notez que la modification d'un commit dans Git exige que tous les commits qui le suivent alse être changé. Ceci est déconseillé si vous avez publié cette partie de l'histoire, et quelqu'un peut avoir à construire leurs travaux sur l'histoire qu'il était avant le changement.
Solution alternative aux
git rebase
mentionné dans Amber réponse est d'utiliser greffes mécanisme (voir la définition de Git greffes dans Git Glossaire et de la documentation de.git/info/grafts
fichier dans Le Dépôt Git De Mise En Page documentation) pour changer parent de s'engager, vérifiez qu'il n'chose correcte avec un peu d'histoire de la visionneuse (gitk
,git log --graph
, etc.) et puis utilisergit filter-branch
(comme décrit dans la section "Exemples" de sa page de man) à la rendre permanente (et puis l'enlever de la greffe, et éventuellement supprimer l'original refs soutenu pargit filter-branch
, ou reclone référentiel):NOTE!!!!! Cette solution est différente de rebase solution dans ce
git rebase
serait rebase /transplantation changements, tandis que les greffes de base de la solution serait tout simplement de reparent s'engage comme, ne prenant pas en compte les différences entre la vieille mère et le nouveau parent!git replace
a remplacé git greffes (en supposant que vous avez git 1.6.5 ou plus tard).git-replace
+git-filter-branch
? Dans mon test,filter-branch
semblait égard, le remplacement, la relocalisation de l'arbre tout entier.git replace
crée en place transférable de remplacement; push sera rapide-vers l'avant, mais vous devez pousserrefs/replace
pour transférer des remplacements d'avoir corrigé l'histoire. HTHPour clarifier les réponses ci-dessus, et sans vergogne fiche de mon propre script:
Cela dépend si vous voulez "rebase" ou "reparent". Un rebase, comme suggéré par le Orange, se déplace autour de diff. Un reparent, comme suggéré par le Jakub et Chris, se déplace autour de instantanés de l'ensemble de l'arbre. Si vous voulez reparent, je vous suggère d'utiliser
git reparent
plutôt que de faire le travail manuellement.Comparaison
Supposons que vous avez sur la photo de gauche et vous voulez qu'il ressemble sur la photo de droite:
À la fois complet et reparenting va produire la même image, mais la définition de
C'
diffère. Avecgit rebase --onto A B
,C'
ne contient pas les modifications introduites parB
. Avecgit reparent -p A
,C'
sera identique àC
(sauf queB
ne seront pas dans l'histoire).reparent
script, il fonctionne à merveille; fortement recommandée. Je vous recommande également la création d'une nouvellebranch
étiquette, et àcheckout
cette branche avant d'appeler (comme la direction générale de l'étiquette va se déplacer).