Come spostare determinati commit per essere basato su un altro ramo in git?


381

La situazione:

  • il maestro è a X
  • quickfix1 è in X + 2 commit

Tale che:

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

Quindi ho iniziato a lavorare su quickfix2, ma per caso ho preso quickfix1 come il ramo di origine da copiare, non il master. Ora quickfix2 è su X + 2 commit + 2 commit rilevanti.

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

Ora voglio avere un ramo con quickfix2, ma senza i 2 commit che appartengono a quickfix1.

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

Ho provato a creare una patch da una certa revisione in quickfix2, ma la patch non conserva la cronologia del commit. C'è un modo per salvare la mia cronologia di commit, ma avere un ramo senza modifiche in quickfix1?



8
@Kevin Quella domanda si pone solo sullo spostamento di commit da un ramo all'altro, questo ha il requisito aggiuntivo di non includere i commit quickfix1. (Nota anche la differenza nelle risposte.)
Scott Weldon,

Risposte:


372

Questo è un classico caso di 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 

Quindi dovresti andare

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

per:

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

È meglio farlo su un albero di lavoro pulito.
Vedigit config --global rebase.autostash true , specialmente dopo Git 2.10 .


24
Fai attenzione che questi passaggi modificheranno la cronologia di quickfix2, quindi se hai già condiviso il ramo, usa invece cherry-picking (vedi le risposte seguenti).
Max Chernyak,

Solo per i record: con log è sufficiente trascinare di SmartGit q2aOnto Xe selezionare Rebase 2 impegna tra le opzioni della finestra di dialogo che si verificano.
Thomas S.

1
@ThomasS. Interessante. Questa è una bella implementazione della GUI di a git rebase --onto.
VonC,

1
Devo ammetterlo, faccio cose stupide come impegnarmi nel ramo sbagliato più spesso di quanto dovrei davvero, la GUI della visualizzazione del registro di SmartGit mi ha salvato così tante volte con la stessa situazione.
WORMSS

1
@Cosine concordato. Ho modificato la mia risposta per aggiungere il riferimento alla rebase.autostashconfigurazione: ciò eviterà qualsiasi perdita di lavori in corso nell'albero di lavoro quando si esegue un rebase.
VonC,

155

È possibile utilizzare git cherry-pickper selezionare semplicemente il commit su cui si desidera copiare.

Probabilmente il modo migliore è quello di creare il ramo dal master, quindi in quel ramo utilizzare git cherry-picki 2 commit da quickfix2 che si desidera.


Questa è anche l'opzione migliore se vuoi spostare solo un commit. Grazie.
Alex

142

La cosa più semplice che puoi fare è scegliere una gamma di ciliegie. Fa lo stesso del rebase --ontoma è più facile per gli occhi :)

git cherry-pick quickfix1..quickfix2

6
inoltre, non perde gli commit originali, IIUC, quindi sembra preferibile per "play-it-safe" come me;) o rebase --ontoconserva anche le modifiche originali?
Akavel,

6
entrambi rebasee cherry-pickti danno nuove chiavi SHA. Questo perché ogni commit è un'istantanea unica del repository.
Christoph,

6
Il significato di @akavel è che cherry-pick manterrà i commit originali nella loro filiale, il che è vero
Mr_and_Mrs_D

4
Per quanto valga la pena, ho provato ad cherry-pickuna gamma come in questa risposta e questo ha confuso il mio repository. Ho dovuto fare i singoli cherry-pickper ogni commit. (E forse è ovvio, ma nel caso in cui qualcuno stia lottando, devi cherry-picknell'ordine cronologico in cui sono stati applicati i tuoi impegni.)
carmenismo

3
git checkoutè cruciale qui. qual è la tua TESTA :)?
Sławomir Lenart,

28

Credo che sia:

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

3
cherry-pickfunziona con hash di commit, quindi, se vuoi semplicemente prendere un commit da qualche parte e metterlo da qualche altra parte, questa è la strada da percorrere. Assicurati solo di fare checkout <branch>prima il ramo corretto.
John Leidegren,

-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]

Altri comandi più utili qui con spiegazione: Guida Git

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.