Come generare una patch git per un commit specifico?


1233

Devo scrivere uno script che crei patch per un elenco di numeri di commit SHA1.

Ho provato ad usare git format-patch <the SHA1>, ma questo ha generato una patch per ogni commit da quel SHA1. Dopo aver generato alcune centinaia di patch, ho dovuto terminare il processo.

C'è un modo per generare una patch solo per SHA1 specifico?

Risposte:


1991

Provare:

git format-patch -1 <sha>

o

git format-patch -1 HEAD

Secondo il collegamento di documentazione sopra, il -1flag indica a git quanti commit devono essere inclusi nella patch;

- <n>

     Prepara le patch dagli commit più in alto.


Applicare la patch con il comando:

git am < file.patch

211
Applicazione della patch: git apply --stat file.patch# mostra le statistiche. git apply --check file.patch# verifica la presenza di errori prima di applicare. git am < file.patch# applica finalmente la patch.
Adrian,

3
Non sembra funzionare se l'ultimo commit è un'unione da un altro ramo.
Lex Li

2
Per applicare la patch sui file usando i finali di riga CRLF:git am --keep-cr < mypatch.patch
Michael Schmeißer,

40
Utilizzare git am -3 < file.patchper applicare utilizzando un'unione a tre vie che consente di risolvere i conflitti utilizzando git mergetoolsuccessivamente (o modificando manualmente) trovato qui .
Matt,

6
Questo comando funziona anche solo per uno o più file specifici dal commit: git format-patch -1 <sha> path/to/file.jsquesto creerà una patch contenente solo i diff per il file.js
Kristóf Dombi,

281

Per generare le patch dal commit più in alto da un hash sha1 specifico:

git format-patch -<n> <SHA1>

Le ultime 10 patch dalla testa in un singolo file di patch:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch

2
puoi per favore essere così gentile da fornire un esempio per il primo comando
Kasun Siyambalapitiya,

1
git format-patch -1 HEADgenererà patch per il commit più recente
Sriram Murali,

1
scusatemi per averlo chiesto, quindi quando si tratta di -2generare patch per gli ultimi 2 commit lo è, e un'altra cosa da chiarire è che il comando got format-patch -2 HEADè lo stesso della lineagit format-patch HEAD~2
Kasun Siyambalapitiya,

85

Supponi di avere il commit id 2 dopo il commit 1 che saresti in grado di eseguire:

git diff 2 1 > mypatch.diff

dove 2 e 1 sono hash SHA.


Grazie dookehster per la risposta. Ciò significa che ho bisogno della sceneggiatura per trovare i commit che hanno preceduto quelli a cui sono interessato. Speravo di poterlo evitare.
elle,

11
@elle, no, non lo fai git diff hash^ hash. "hash ^" indica il commit precedente. (ma, naturalmente, la risposta di manojlds è migliore)
J-16 SDiZ,

2
git show HEAD > mypatch.diffmentre sei sul commit dovrebbe fare lo stesso.
andho,

1
@dookehester è corretto o è il contrario,git diff 1 2
Kasun Siyambalapitiya,

1
Questo non includerà alcun file binario nel diff.
stuckj

55

Questo comando (come già suggerito da @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Sostituisci HEADcon hash o range specifici.

genererà il file patch per l'ultimo commit formattato per assomigliare al formato della cassetta postale UNIX.

-<n> - Prepara le patch dagli commit più in alto.

Quindi è possibile riapplicare il file patch in un formato cassetta postale:

git am -3k 001*.patch

Vedi: man git-format-patch.


Grazie! Penso che valga la pena notare che l'applicazione della patch creerà un commit con un messaggio di commit preceduto da [PATCH]. È facile da risolvere, però
Mike S,

2
Fenomenale. OP, non l'hai accettato, perché ...? @MikeS No, non lo fa più di qualsiasi altra gitpatch formattata, almeno se l'utente la applica nel modo corretto.
underscore_d

2
@MikeS Non ho davvero indagato sul perché, ma tralasciando la -kbandiera ( git am -3) ho risolto questo modulo (nessun PATCH[0/10]messaggio di commit). Git versione 2.20.1.windows.1
jannis

31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Soluzione semplice e veloce.


5
Inoltre, non dimenticare di chiamare git apply --check patch-file-nameprima di applicare una patch. Ciò contribuirà ad evitare problemi.
iamantony,

16

Se vuoi essere sicuro che la patch (commit singolo) verrà applicata su un commit specifico, puoi usare la nuova opzione git 2.9 (giugno 2016) git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Vedi commit bb52995 , commit 3de6651 , commit fa2ab86 , commit ded2c09 (26 aprile 2016) di Xiaolong Ye (``) .
(Unita da Junio ​​C Hamano - gitster- in commit 72ce3ff , 23 maggio 2016)

format-patch: aggiungi l' --baseopzione ' ' per registrare le informazioni dell'albero di base

I manutentori o i tester di terze parti potrebbero voler conoscere l'albero di base esatto a cui si applica la serie di patch. Insegna a git format-patch --baseun'opzione ' ' per registrare le informazioni dell'albero di base e aggiungerle alla fine del primo messaggio (o la lettera di accompagnamento o la prima patch della serie).

Le informazioni sull'albero di base sono costituite dal "commit di base", che è un commit noto che fa parte della parte stabile della storia del progetto su cui tutti gli altri lavorano, e zero o più "patch prerequisiti", che sono ben note patch in volo che non fanno ancora parte del "commit di base" che devono essere applicate sopra "commit di base" in ordine topologico prima di poter applicare le patch.

Il "commit di base" viene mostrato come " base-commit:" seguito dal 40-hex del nome dell'oggetto di commit.
Una "patch prerequisito" viene mostrata come " prerequisite-patch-id:" seguita dal "id patch" 40-hex, che può essere ottenuto passando la patch attraverso il git patch-id --stablecomando " ".


Git 2.23 (3 ° trimestre 2019) lo migliorerà, poiché l '" --base" opzione di " format-patch" ha calcolato le patch-idspatch dei prerequisiti in modo instabile, che è stato aggiornato per essere calcolato in modo compatibile con " git patch-id --stable".

Vedi commit a8f6855 , commit 6f93d26 (26 aprile 2019) di Stephen Boyd ( akshayka) .
(Unita da Junio ​​C Hamano - gitster- in commit 8202d12 , 13 giu 2019)

format-patch: rendere --base patch-idstabile l'output

Non stavamo cancellando il contesto ogni volta che elaboravamo un pezzo nel patch-idcodice di generazione diff.c, ma lo facevamo quando generavamo patch-id "stabili" con lo patch-idstrumento " ".

Portiamo quella logica simile da patch-id.cdentro a diff.ccosì possiamo ottenere lo stesso hash quando generiamo patch-id per format-patch --base="tipi di invocazioni di comandi.


Prima di Git 2.24 (Q4 2019), " git format-patch -o <outdir>" ha fatto un equivalente di " mkdir <outdir>" non " mkdir -p <outdir>", che viene corretto.

Vedi commit edefc31 (11 ott 2019) di Bert Wesarg ( bertwesarg) .
(Unito da Junio ​​C Hamano - gitster- in commit f1afbb0 , 18 ott 2019)

format-patch: crea i componenti principali della directory di output

Approvato da: Bert Wesarg

'git format-patch -o' ha fatto un equivalente di 'mkdir' non 'mkdir -p', che viene corretto.

Evita l'uso di " adjust_shared_perm" nelle directory principali che potrebbero avere implicazioni per la sicurezza. Ottenuto disabilitando temporaneamente ' config.sharedRepository' mi piace ' git init'.


Con Git 2.25 (Q1 2020), " git rebase" non ha funzionato bene quando format.useAutoBaseè stata impostata la variabile di configurazione, che è stata corretta.

Vedi commit cae0bc0 , commit 945dc55 , commit 700e006 , commit a749d01 , commit 0c47e06 (04 dic 2019) di Denton Liu ( Denton-L) .
(Unita da Junio ​​C Hamano - gitster- in commit 71a7de7 , 16 dic 2019)

rebase: correzione del format.useAutoBaseguasto

Segnalato da: Christian Biesinger
Firmato da: Denton Liu

Con format.useAutoBase = true, l'esecuzione di rebase ha provocato un errore:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Risolvilo passando sempre --no-basealla patch di formattazione da rebase in modo che l'effetto di format.useAutoBasesia negato.


8

Per generare il percorso da un commit specifico (non l'ultimo commit):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE

5

se vuoi solo diff il file specificato, puoi:

git diff master 766eceb - connessioni /> 000-mysql-connettore.patch


0

Con il mio background mercuriale stavo per usare:

git log --patch -1 $ID > $file

Ma sto pensando di utilizzare git format-patch -1 $IDora.


-5

Qual è il modo di generare una patch solo per SHA1 specifico?

È abbastanza semplice:

Opzione 1. git show commitID > myFile.patch

Opzione 2. git commitID~1..commitID > myFile.patch

Nota: sostituire commitIDcon l'ID commit effettivo (codice commit SHA1).


3
L'opzione 1 è decisamente sbagliata e non è correlata alla domanda.
Anshuman Manral,

3
Anche l'opzione 2 è un comando non valido. Si otterrà un errore del tipo: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de27ae79d95223320797953f3ae0da Vedi 'git --help'.
Si prega di
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.