443 votes

Comment déplacer certains commits pour qu'ils soient basés sur une autre branche dans git ?

La situation :

  • le maître est à X
  • quickfix1 est à X + 2 commits

Telle que :

o-o-X (master HEAD)
     \
      q1a--q1b (quickfix1 HEAD)

Puis j'ai commencé à travailler sur quickfix2, mais par accident j'ai pris quickfix1 comme branche source à copier, et non le master. Maintenant, quickfix2 est à X + 2 commits + 2 commits pertinents.

o-o-X (master HEAD)
     \
      q1a--q1b (quickfix1 HEAD)
              \
               q2a--q2b (quickfix2 HEAD)

Maintenant je veux avoir une branche avec quickfix2, mais sans les 2 commits qui appartiennent à quickfix1.

      q2a'--q2b' (quickfix2 HEAD)
     /
o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)

J'ai essayé de créer un patch à partir d'une certaine révision dans quickfix2, mais le patch ne préserve pas l'historique des commits. Existe-t-il un moyen de sauvegarder l'historique des livraisons, mais d'avoir une branche sans changement dans quickfix1 ?

0 votes

14 votes

@Kevin Cette question ne porte que sur le déplacement de commits d'une branche à l'autre, celle-ci a l'exigence supplémentaire suivante no y compris les commits sur quickfix1 . (Notez également la différence dans les réponses).

418voto

VonC Points 414372

C'est un cas classique de rebase --onto :

 # let's go to current master (X, where quickfix2 should begin)
 git checkout master

 # replay every commit *after* quickfix1 up to quickfix2 HEAD.
 git rebase --onto master quickfix1 quickfix2 

Vous devriez donc passer de

o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)
              \
               q2a--q2b (quickfix2 HEAD)

à :

      q2a'--q2b' (new quickfix2 HEAD)
     /
o-o-X (master HEAD)
     \ 
      q1a--q1b (quickfix1 HEAD)

Il est préférable de le faire sur un arbre de travail propre.
Voir git config --global rebase.autostash true notamment après Git 2.10 .

29 votes

Attention, ces étapes vont modifier l'historique de quickfix2, donc si vous avez déjà partagé la branche, utilisez plutôt le cherry-picking (voir les réponses suivantes).

1 votes

Juste pour mémoire : avec le journal de SmartGit, il suffit de faire glisser q2a sur X et sélectionnez Rebase 2 commits dans les options de la boîte de dialogue d'occurrence.

1 votes

@ThomasS. Intéressant. C'est une belle implémentation GUI d'un git rebase --onto .

178voto

DJ. Points 2663

Vous pouvez utiliser git cherry-pick pour juste choisir le commit que vous voulez copier.

La meilleure façon est probablement de créer une branche à partir de master, puis dans cette branche d'utiliser git cherry-pick sur les 2 commits de quickfix2 que vous voulez.

1 votes

C'est également la meilleure option si vous souhaitez déplacer un seul engagement. Merci.

170voto

Christoph Points 4662

La chose la plus simple que vous pouvez faire est de choisir une gamme. Cela fait la même chose que le rebase --onto mais c'est plus facile pour les yeux :)

git cherry-pick quickfix1..quickfix2

6 votes

De plus, il ne perd pas les commits originaux, IIUC, donc semble préférable pour les "play-it-safes" comme moi ;) ou est-ce que rebase --onto préserver également les modifications originales ?

6 votes

Les deux rebase et cherry-pick vous donner de nouvelles clés SHA. C'est parce que chaque commit est un unique instantané du référentiel.

6 votes

Ce que @akavel voulait dire, c'est que cherry-pick conservera les commits originaux dans sa branche, ce qui est vrai.

35voto

Matthew Flaschen Points 131723

Je crois que c'est :

git checkout master
git checkout -b good_quickfix2
git cherry-pick quickfix2^
git cherry-pick quickfix2

3 votes

cherry-pick fonctionne avec les hashs de commit, donc, si vous voulez juste récupérer un commit quelque part et le mettre ailleurs, c'est la solution. Assurez-vous simplement que vous faites le checkout <branch> de la bonne branche en premier.

-2voto

Gopher Points 1
// on your branch that holds the commit you want to pass
$ git log
// copy the commit hash found
$ git checkout [branch that will copy the commit]
$ git reset --hard [hash of the commit you want to copy from the other branch]
// remove the [brackets]

Autres commandes plus utiles ici avec explication : Guide Git

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X