Guida

git cherry-pick: come spostare un singolo commit in un altro branch

Aggiornato: · Skillaria.Top

git cherry-pick prende le modifiche del commit indicato e crea sul branch corrente un nuovo commit con lo stesso diff e lo stesso messaggio, ma con un hash diverso. Spostatevi sul branch di destinazione ed eseguite git cherry-pick <hash>; in caso di conflitto correggete i file, fate git add e git cherry-pick --continue.

git cherry-pick porta le modifiche di un singolo commit specifico sul branch corrente, senza unire l'intero branch. Git calcola il diff del commit scelto rispetto al suo genitore, lo applica al vostro HEAD e crea un nuovo commit, con lo stesso messaggio e lo stesso autore ma con un hash diverso, perché ha un genitore diverso.

Lo scenario tipico: nel branch di una feature avete corretto un bug, e la correzione serve con urgenza nel branch di release, dove la feature non è ancora pronta. Unire tutto il branch non si può, un solo commit sì.

Come spostare un commit in un altro branch

Prima trovate l'hash del commit che vi serve, poi spostatevi sul branch in cui volete portarlo ed eseguite cherry-pick.

# 1. Troviamo il commit nel branch feature
git log --oneline feature
a1b2c3d Correggi la divisione per zero nel calcolo dello sconto
9f8e7d6 Aggiungi la nuova schermata di pagamento

# 2. Passiamo al branch di destinazione
git switch release-1.4

# 3. Portiamo il commit
git cherry-pick a1b2c3d
[release-1.4 4e5f6a7] Correggi la divisione per zero nel calcolo dello sconto
 Date: Mon Oct 5 14:12:03 2026 +0200
 1 file changed, 3 insertions(+), 1 deletion(-)

Notate che il nuovo commit ha ricevuto l'hash 4e5f6a7, non a1b2c3d. Sono due oggetti diversi con le stesse modifiche. Il branch di partenza feature non cambia.

Al posto dell'hash potete passare qualsiasi riferimento a un commit: git cherry-pick feature prende l'ultimo commit del branch feature, git cherry-pick feature~2 il terzo dalla fine.

Come spostare più commit

Elencandoli

Gli hash si possono passare come elenco: Git li applica nell'ordine indicato, creando altrettanti nuovi commit.

git cherry-pick a1b2c3d 7c8d9e0 3f4a5b6

L'ordine conta: se il secondo commit dipende dal primo e li avete elencati al contrario, otterrete un conflitto o codice rotto. È più sicuro indicarli dal più vecchio al più recente.

Con un intervallo

Per commit consecutivi si usa la sintassi a intervallo. Qui c'è una trappola in cui inciampano quasi tutti: A..B significa «i commit raggiungibili da B ma non da A», quindi A stesso non è incluso nell'intervallo.

# Porta i commit DOPO A fino a B incluso
git cherry-pick A..B

# Porta A e tutto fino a B incluso
git cherry-pick A^..B

Se volete portare tutto ciò che c'è nel branch feature e non in main, è comoda la forma git cherry-pick main..feature. Ma se i commit sono tanti, fermatevi a pensare: forse vi serve un rebase o un merge, non un cherry-pick.

Opzioni utili di git cherry-pick

OpzioneCosa faQuando serve
-xAggiunge al messaggio la riga «(cherry picked from commit …)»Quando si spostano correzioni tra branch pubblici: l'origine resta visibile
-n, --no-commitApplica le modifiche all'indice e alla working directory senza commitVolete unire più commit in uno o ritoccare prima del commit
-e, --editApre l'editor per modificare il messaggioServe adattare il messaggio al branch di destinazione
-s, --signoffAggiunge la riga Signed-off-byProgetti che richiedono il DCO
-m 1Indica il genitore «principale» di un commit di mergeSpostare un commit di merge
--ffFa avanzare il branch se HEAD è il genitore del commit sceltoRaramente; evita di creare un duplicato
--allow-emptyPermette di spostare commit vuoti in origineCommit vuoti di servizio

A cosa serve -x

Tra sei mesi qualcuno vedrà una correzione nel branch di release e vorrà capire da dove arriva. La riga aggiunta da -x dà una risposta diretta:

git cherry-pick -x a1b2c3d
git log -1
    Correggi la divisione per zero nel calcolo dello sconto

    (cherry picked from commit a1b2c3d4e5f60718293a4b5c6d7e8f9012345678)

Usate -x quando il commit di origine è già pubblicato. Se lo spostate da un vostro branch locale che poi eliminerete, il riferimento porterà nel vuoto: lì l'opzione non serve.

Riunire più commit in uno: -n

git cherry-pick -n a1b2c3d 7c8d9e0
git status          # le modifiche di entrambi i commit sono nell'indice
git commit -m "Correzioni al calcolo dello sconto"

Conflitti durante cherry-pick e come risolverli

Un conflitto nasce quando le modifiche del commit non si adattano al codice attuale: nel branch di destinazione le stesse righe sono già diverse. Git si ferma e lo segnala.

git cherry-pick a1b2c3d
Auto-merging src/discount.js
CONFLICT (content): Merge conflict in src/discount.js
error: could not apply a1b2c3d... Correggi la divisione per zero nel calcolo dello sconto
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".

A questo punto avete tre strade:

  1. Risolvere e proseguire. Aprite il file, togliete i marcatori <<<<<<<, =======, >>>>>>> lasciando la variante corretta, poi git add src/discount.js e git cherry-pick --continue.
  2. Saltare il commit. Quando spostate un elenco, git cherry-pick --skip salta il commit problematico e passa al successivo.
  3. Annullare tutto. git cherry-pick --abort riporta il branch allo stato precedente all'operazione.

C'è anche git cherry-pick --quit: interrompe l'operazione ma lascia i commit già applicati e lo stato attuale dei file. È utile quando metà dell'elenco è stata spostata con successo e da lì volete procedere a mano.

Se i conflitti si ripetono sempre uguali (ad esempio, spostate regolarmente correzioni in più branch di release), attivate git config rerere.enabled true: Git ricorderà come avete risolto il conflitto e la volta successiva applicherà la soluzione in automatico.

Come spostare un commit di merge

Un commit di merge ha due genitori, e Git non sa rispetto a quale calcolare il diff. Senza indicazioni otterrete un errore:

git cherry-pick 5d6e7f8
error: commit 5d6e7f8 is a merge but no -m option was given.

L'opzione -m 1 dice: calcola le modifiche rispetto al primo genitore, di solito il branch in cui si è fatto il merge. Così porterete in un solo commit tutto ciò che ha introdotto il branch unito.

git cherry-pick -m 1 5d6e7f8

Tenete presente che dopo questa operazione Git non considererà il branch come unito: in un merge futuro potrebbe tentare di applicare di nuovo le stesse modifiche.

git cherry-pick e git apply: le differenze

git apply viene spesso citato insieme a cherry-pick, perché entrambi i comandi «applicano modifiche». Ma lavorano su dati di partenza diversi.

git cherry-pickgit apply
OrigineUn commit presente nel repositoryUn file di patch (diff)
Crea un commitSì (senza -n)No, modifica solo i file (con --index anche l'indice)
Conserva autore e messaggioSìNo, nella patch non ci sono
ConflittiMerge a tre vie con marcatoriDi default semplice rifiuto; con --3way marcatori
Serve un repository comuneSì, il commit deve essere disponibile in localeNo, la patch si può passare in qualsiasi modo

Esempio d'uso di git apply quando il commit non è nel vostro repository e un collega vi ha mandato il diff come file:

# Il collega esegue
git diff main..fix-discount > fix.patch

# Voi verificate e applicate
git apply --check fix.patch   # verificare se la patch si applica
git apply fix.patch           # applicarla alla working directory
git apply --3way fix.patch    # in caso di differenze, con i marcatori di conflitto

Se dovete passare un commit completo, con autore e messaggio, usate la coppia git format-patch e git am: il primo salva i commit in file, il secondo ne ricava dei commit. In sostanza è un cherry-pick «via e-mail».

Tra l'altro, il cherry-pick da un altro repository è possibile: aggiungetelo come remote, eseguite git fetch e i commit saranno accessibili per hash.

Quando cherry-pick è una cattiva idea

Cherry-pick crea duplicati: la stessa modifica vive nella storia con due hash. In piccole dosi va bene, ma ci sono scenari in cui fa danni.

  • Spostare decine di commit. Se state portando quasi tutto il branch, quello è un rebase o un merge. Qui cherry-pick produce una lunga storia di duplicati e più conflitti.
  • Spostamenti in entrambe le direzioni. Un commit è stato portato da feature a main, poi feature viene unito in main. Di solito Git se la cava (le modifiche coincidono), ma se dopo lo spostamento quelle righe sono state modificate, avrete un conflitto dal nulla.
  • Commit dipendenti. Il commit usa una funzione aggiunta due commit prima. Cherry-pick sposta solo il commit stesso e il codice nel branch di destinazione non compilerà. Verificate sempre build e test dopo lo spostamento.

Una buona pratica per gli hotfix è fare la correzione direttamente nel branch supportato più vecchio e unirla «verso l'alto» in quelli più nuovi. Così cherry-pick serve solo come eccezione.

Come annullare un cherry-pick

Se l'operazione è ancora in corso (conflitto): git cherry-pick --abort. Se il commit è già stato creato e non è stato inviato al server, rimuovetelo:

git reset --hard HEAD~1

Se il commit è già stato pushato su un branch condiviso, non si può riscrivere la storia: create un commit inverso:

git revert 4e5f6a7

E se avete fatto reset e ci avete ripensato, il commit perso si ritrova con git reflog.

Come verificare se un commit è già stato spostato

Dato che gli hash sono diversi, il solito git branch --contains non aiuta. Git sa confrontare i commit in base al contenuto delle modifiche (patch-id):

git cherry -v release-1.4 feature
- a1b2c3d Correggi la divisione per zero nel calcolo dello sconto
+ 9f8e7d6 Aggiungi la nuova schermata di pagamento

Il meno significa che in release-1.4 c'è già una modifica equivalente, il più che non c'è ancora. In alternativa c'è git log --cherry-pick --oneline release-1.4...feature, che nasconde i commit gemelli. Se avete usato -x, basta cercare nel messaggio: git log --grep="cherry picked from commit a1b2c3d".

In sintesi

git cherry-pick è uno strumento di precisione: portare un hotfix in una release, recuperare un commit utile da un branch abbandonato, rimediare a un commit fatto per sbaglio nel posto sbagliato. Ricordate tre cose: il nuovo commit riceve un nuovo hash, l'intervallo A..B non include A, e per i branch pubblici conviene aggiungere -x. Se dovete spostare non un commit ma un diff da un file, usate git apply. Rebase, stash, cherry-pick e tag sono trattati in dettaglio e in pratica nel corso su Git.

Domande frequenti

cherry-pick modifica il branch di origine?

No. Il commit originale resta dov'è, e nel branch corrente compare una sua copia con un nuovo hash.

Si può fare cherry-pick di un commit da un branch remoto?

Sì. Eseguite git fetch, dopodiché il commit è accessibile per hash o come origin/nome-branch e si può passare a git cherry-pick.

Perché dopo cherry-pick il commit ha un hash diverso?

L'hash dipende dal genitore, dall'ora del commit e dal contenuto dell'albero. La copia ha un genitore e un orario del committer diversi, quindi anche l'hash è diverso.

Con cherry-pick si conserva l'autore del commit?

Sì, l'autore e la data di creazione vengono presi dal commit originale, mentre il committer diventate voi con la data attuale.

Cosa fare se cherry-pick dice che il commit è vuoto?

Significa che queste modifiche sono già presenti nel branch. Saltatelo con git cherry-pick --skip o registratelo come vuoto con git commit --allow-empty.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Git da zero a sviluppatore sicuro».

Vai al corso