2012-03-18 3 views
28

J'ai deux branches git, « A » et « B », et archivages numéro 1 à travers 8. Mon histoire ressemble à cegit: branche mobile tête

1 -> 2 -> 3 -> 4[A] -> 5 -> 6 -> 7 -> 8[B] 

Je veux changer si mes regards d'histoire comme ceci:

1 -> 2 -> 3 -> 4 -> 5 -> 6[A] -> 7 -> 8[B] 

qui est, je veux déplacer la tête de la branche A de commettre 4 à 6. commettras

Quelles commandes dois-je utiliser pour ce faire?

Répondre

41

Vous pouvez exécuter:

git branch -f A 6 
+1

Cela fonctionne dans cette situation car A ne contient réellement rien; il pointe juste vers le point de branchement et ainsi nous déplaçons le pointeur ailleurs sans rien perdre. Supposons que A a eu quelques commits? Ensuite, vous devez faire un 'git rebase' pour reporter les commits. C'est plus général et devrait gérer ce cas trivial "branche vide" aussi. – Kaz

+4

@Kaz, git a des branches légères, donc elles ne "contiennent" rien. Ils sont juste une note collante mobile attachée à un commit. Ma réponse est pour ce scénario, une histoire de branche linéaire.Si ce n'était pas linéaire, je regarderais ce que le PO voulait réellement et trouverais une solution. –

+0

Vous pourriez dire cela à propos de CVS aussi alors. Une branche ne contient rien. C'est juste un tag de branche ("sticky note") indiquant un numéro de branche comme 1.2.0.2. CVS a-t-il une ramification légère? :) – Kaz

13
git checkout A 
git reset --hard 6 
+6

Cela fonctionne, mais est la "dure". La raison pour laquelle cela fonctionne est que si vous êtes "sur une branche" (en termes git), 'git reset --hard ' déplace la branche pour vous. Mais 'git branch -f ' re-pointe la branche en une étape. Il y a une limitation: 'git branch -f' ne vous laissera pas déplacer votre branche actuelle. Donc, si vous êtes déjà "sur la branche A" (comme indiqué par la sortie 'git branch'), vous devez utiliser cette méthode' git reset --hard'. (Ou quittez la branche A, mais cela devient idiot. :-)) – torek

7

C'est un cas particulier de rebasage, juste que la branche est vide:

git checkout A 
git rebase B 

rebase est plus générale; il gère ce cas aussi:

Avant:

    A1 -> A2 -> [A] 
       /
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8[B] 

Après:

         A1' -> A2' -> [A] 
            /
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8[B] 

A1' et A2' sont fusionnées pour tenir compte du delta entre 4 et 8 sur la branche mère. Git rebase gère ce cas trivial sans tracas. J'ai créé un repo avec deux commits sur master et une branche br pointant vers le premier commit.

$ git checkout br 
Switched to branch 'br' 
$ git rebase master 
First, rewinding head to replay your work on top of it... 
Fast-forwarded br to master. 

Poof, fait. Le journal affiche maintenant la branche pointant vers la deuxième validation.

On peut aussi y parvenir « Après »: [grâce à M. Flaschen pour remarquer ce qui manquait]:

      A1'' -> A2'' -> [A] 
         /
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8[B] 

Au lieu de rebasage à la branche B, nous nommerions la allouent spécifique 6, par exemple

git checkout A 
git rebase 6 # rather than rebase B 

Quand il n'y a pas A1 et A2 commits, cela réduit à la question initiale: déplacer le [A] pointeur de 4 à 6.

+0

Le cas avant ne correspond pas à la question. Dans la question, aucun commit n'est seulement sur A. –

+0

Le cas avant est une généralisation de la question. A1 et A2 n'existent pas. Une liste vide est une liste. – Kaz

+1

Votre cas ultérieur ne correspond pas non plus. [A] pointe vers 8, plutôt que 6. En outre, je ne suis pas sûr que cette généralisation aide à répondre à la question initiale. –