Come cherry-pick multipli commit
-
13-09-2019 - |
Domanda
Ho due rami. Commit a
è la testa di uno, mentre l'altro ha b
, c
, d
, e
e f
in cima a
. Voglio spostare c
, d
, e
e f
al primo ramo, senza commettere b
. Utilizzando ciliegia scegliere è facile: cassa primo ramo ciliegio scegliere uno per uno c
a f
e rebase secondo ramo sul primo. Ma esiste un modo per cherry-pick tutti c
-f
in un solo comando?
Ecco una descrizione visiva dello scenario (grazie JJD ):
Soluzione
Git 1.7.2 ha introdotto la possibilità di cherrypick una serie di commit. Dal note :
git cherry-pick" ha imparato a raccogliere una serie di commit (Ad esempio "cherry-pick a..b" e "ciliegia-pick --stdin"), così ha fatto "git ripristinano "; questi non supportano il controllo della sequenza di bello" aggiustano [-I]" ha, però.
compresi i commenti importanti (crediti a rispettivi autori)
Nota 1: Nel "a..b cherry-pick" forma, A dovrebbe avere più di B. Se sono nell'ordine sbagliato il comando fallire in modo silenzioso. - damian
Nota 2: Inoltre, questo non sarà cherry-pick A, ma piuttosto tutto dopo A fino al B. - J. B. RAINSBERGER
Nota 3: per includere un solo tipo git cherry-pick A ^ .. B - sschaef
Altri suggerimenti
Il modo più semplice per farlo è con l'opzione onto
a rebase
. Supponiamo che il ramo che attuali finiture a a
si chiama mybranch e questo è il ramo che si desidera spostare c
-f
su.
# checkout mybranch
git checkout mybranch
# reset it to f (currently includes a)
git reset --hard f
# rebase every commit after b and transplant it onto a
git rebase --onto a b
O la richiesta one-liner:
git rebase --onto a b f
È possibile utilizzare una combinazione di serie di git rebase
e git branch
di applicare un gruppo di commit su un altro ramo. Come già inviato da wolfc il primo comando si copia effettivamente i commit. Tuttavia, il cambiamento non è visibile finché non si aggiunge un nome ramo alla cima più commit del gruppo.
Si prega di aprire l'immagine in una nuova scheda ...
Per riassumere i comandi in formato testo:
- Apri gitk come un processo indipendente utilizzando il comando:.
gitk --all &
- Esegui
git rebase --onto a b f
. - Premere F5 in gitk . Niente cambia. Ma nessuno
HEAD
è segnato. - Esegui
git branch selection
- Premere F5 in gitk . Viene visualizzata la nuova filiale con i suoi commit.
Questo dovrebbe chiarire le cose:
- Commit
a
è la nuova destinazione principale del gruppo. - Commit
b
è il commit prima del primo commit del gruppo (esclusiva). - Commit
f
è l'ultimo commit del gruppo (compreso).
In seguito, è possibile utilizzare git checkout feature && git reset --hard b
per eliminare il c
impegna fino f
dal ramo feature
.
In aggiunta a questa risposta, ho scritto un post sul blog che descrive i comandi in un altro scenario che dovrebbe aiutare ad utilizzare generalmente.
Per applicare J. B. RAINSBERGER e commenti di sschaef per rispondere specificamente alla domanda ... Per utilizzare un intervallo cherry-pick in questo esempio:
git checkout a
git cherry-pick b..f
o
git checkout a
git cherry-pick c^..f
Se avete revisioni selettivi per unire, diciamo A, C, F, J da A, B, C, D, E, F, G, H, I, J si impegna, è sufficiente utilizzare sotto comando:
git cherry-pick A C F J
git rev-list --reverse b..f | xargs -n 1 git cherry-pick
Per scegliere ciliegia da un commit id fino alla punta del ramo, è possibile utilizzare:
git cherry-pick commit_id^..branch_name
git format-patch --full-index --binary --stdout range... | git am -3
In realtà, il modo più semplice per farlo potrebbe essere quello di:
- registrare la fusione-base fra i due rami:
MERGE_BASE=$(git merge-base branch-a branch-b)
- fast-forward o rebase il ramo più vecchio sul ramo più recente
-
rebase ramo risultante su se stessa, partendo dalla base merge dal passaggio 1, e rimuovere manualmente commit che non sono desiderate:
git rebase ${SAVED_MERGE_BASE} -i
In alternativa, se ci sono solo un paio di nuovi commit, saltare il passaggio 1, e semplicemente usare
git rebase HEAD^^^^^^^ -i
nella prima fase, utilizzando abbastanza
^
di superare l'unione-base.
Si vedrà qualcosa di simile nel rebase interattivo:
pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f
Quindi rimuovere linee b (e tutti gli altri che si desidera)
Ecco uno script che vi permetterà di cherry-pick multipla si impegna in fila semplicemente raccontando lo script che si dirama origine e di destinazione per le scelte di ciliegio e il numero di commit:
https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81
Per cherry-pick dal ramo master (utilizza il ramo corrente come sorgente):
./gcpl.sh -m
Per cherry-pick gli ultimi 5 commit dal vostro ramo 6.19.x da padroneggiare:
./gcpl.sh -c 5 -s 6.19.x -t master