Crea una patch git dalle modifiche nella directory di lavoro corrente


880

Supponiamo di aver apportato modifiche non confermate nella mia directory di lavoro. Come posso fare una patch da quelli senza dover creare un commit?


29
La risposta accettata dovrebbe probabilmente essere cambiata, dato che la seconda risposta è quasi quattro volte più popolare.
Tim Ogilvy,

5
@TimOgilvy concordato. OP dovrebbe farlo. La seconda risposta è molto più popolare e fornisce maggiori informazioni
John Demetriou,

1
Penso che valga la pena menzionare la necessità di patch anche da modifiche non confermate nel titolo.
2

Risposte:


401

git diffper modifiche non messe in scena. git diff --cachedper modifiche graduali.


12
sì, git diff è l'inverso di git applicare
Spike Gronim

33
git format-patchinclude anche diff binari e alcune meta info. In realtà sarebbe la soluzione migliore per la creazione di una patch, ma questo funziona solo per fonti / modifiche registrate, giusto?
Eric

20
A volte potrebbe essere utile creare una patch relativa alla directory corrente. Per raggiungere questo obiettivo, utilizzaregit diff --relative
ejboy

30
git diff> a.patch per scriverlo in un file
qasimzee,

139
Confinante con il sarcastico, la risposta che segue è più utile.
Air

1865

Se non hai ancora eseguito il commit delle modifiche, allora:

git diff > mypatch.patch

Ma a volte capita che parte delle cose che stai facendo siano nuovi file che non sono tracciati e non saranno nel tuo git diffoutput. Quindi, un modo per fare una patch è mettere in scena tutto per un nuovo commit ( git addogni file o solo git add .) ma non eseguire il commit, quindi:

git diff --cached > mypatch.patch

Aggiungi l'opzione 'binary' se vuoi aggiungere file binari alla patch (es. File mp3):

git diff --cached --binary > mypatch.patch

È possibile applicare successivamente la patch:

git apply mypatch.patch

Nota: è anche possibile utilizzare --stagedcome sinonimo di --cached.


128
Grazie mille per l'esempio. Al contrario della risposta accettata mostri ai comandi come farlo e non solo parlare. Molto utile e ha funzionato perfettamente per me :)
nuala il

4
Ho fatto esattamente questo e ho ottenuto "input fatali: non riconosciuti" durante l'esecuzione di git apply. Qualche idea su cosa possa causare questo e come risolverlo?
Vitaly,

6
@Vitaly: la tua patch è leggibile se la apri con un editor di testo? dovrebbe essere pulito senza caratteri strani, ad esempio se l'impostazione color.diff è impostata, la patch avrà alcuni "caratteri colore" che possono far fallire "git apply", in questo caso provare git diff --no-color. Altrimenti, sembra un problema di codifica.
jcarballo,

3
Relativo a "nuovi file non tracciati": "git diff" e "git diff --cached" funzionano solo se è stato chiamato per primo "git add <file>". (Sono nuovo di Git e mi chiedevo perché avessi sempre una patch vuota)
Anonimo

5
Questo mi ha fatto uscire da uno strano inferno di merge / rebase abbastanza facilmente, grazie :)
John Hunt,

86

git diffe git applyfunzionerà per i file di testo, ma non funzionerà per i file binari.

Puoi facilmente creare una patch binaria completa, ma dovrai creare un commit temporaneo. Una volta effettuati i tuoi commit temporanei, puoi creare la patch con:

git format-patch <options...>

Dopo aver creato la patch, esegui questo comando:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Questo ripristinerà i tuoi commit temporanei. Il risultato finale lascia la tua copia di lavoro (intenzionalmente) sporca con le stesse modifiche che avevi originariamente.

Sul lato ricevente, è possibile utilizzare lo stesso trucco per applicare le modifiche alla copia di lavoro, senza avere la cronologia di commit. Basta applicare le patch e git reset --mixed <SHA of commit *before* the patches>.

Tieni presente che potresti dover essere ben sincronizzato affinché l'intera opzione funzioni. Ho visto alcuni errori nell'applicazione delle patch quando la persona che le stava realizzando non aveva annullato tutti i cambiamenti che avevo. Probabilmente ci sono modi per farlo funzionare, ma non ho studiato molto.


Ecco come creare le stesse patch in Tortoise Git (non che consiglio di usare questo strumento):

  1. Impegna i tuoi cambiamenti di lavoro
  2. Fare clic con il tasto destro sulla directory radice del ramo e fare clic su Tortoise Git->Create Patch Serial
    1. Scegli quale intervallo ha senso ( Since: FETCH_HEADfunzionerà se sei ben sincronizzato)
    2. Crea le patch
  3. Fare clic con il tasto destro sulla directory radice del ramo e fare clic su Tortise Git->Show Log
  4. Fare clic con il pulsante destro del mouse sul commit prima dei commit temporanei e fare clic sureset "<branch>" to this...
  5. Seleziona l' Mixedopzione

E come applicarli:

  1. Fare clic con il tasto destro sulla directory radice del ramo e fare clic su Tortoise Git->Apply Patch Serial
  2. Seleziona le patch corrette e applicale
  3. Fare clic con il tasto destro sulla directory radice del ramo e fare clic su Tortise Git->Show Log
  4. Fare clic con il pulsante destro del mouse sul commit prima dei commit della patch e fare clicreset "<branch>" to this...
  5. Seleziona l' Mixedopzione

5
Tecnicamente ciò richiede la creazione di un commit che OP ha chiesto di evitare, ma è temporaneo e la risposta è utile a prescindere.
davenpcj,

33

Per creare una patch con entrambi i file modificati e nuovi (messi in scena) è possibile eseguire:

git diff HEAD > file_name.patch

Grazie, nel mio caso, questa risposta funziona, ma git diff --cached > mypatch.patchnon funziona.
estrazione

Ho una domanda: può file_name.patchessere utilizzata dal patchcomando? Sono compatibili tra loro?
Rakshith Ravi,

git diff + git diff --cached / staged == git diff HEAD (mostra tutte le modifiche dall'ultimo commit)
K. Simbolo

20

Mi piace:

git format-patch HEAD~<N>

dove <N> è il numero degli ultimi commit da salvare come patch.

I dettagli su come usare il comando sono nel DOC

UPD
Qui puoi trovare come applicarli allora.

UPD Per coloro che non hanno avuto l'idea di format-patch
Aggiungi alias:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Quindi, in qualsiasi directory del repository del progetto, eseguire:

git make-patch

Questo comando verrà creato 0001-uncommited.patchnella directory corrente. Patch conterrà tutte le modifiche e i file non tracciati visibili al comando successivo:

git status .

@jcarballo: ho aggiornato la risposta. Sentiti libero di lasciarmi qualsiasi avviso tu abbia.
Eugen Konkov,

2
Esiste un modo più semplice della creazione di un commit e di un commit. git diff --cached --binary
Gaurav Agarwal

9

Se vuoi fare binario, dai --binaryun'opzione quando corri git diff.


0

Potremmo anche specificare i file, per includere solo i file con relative modifiche, in particolare quando si estendono su più directory ex

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

Ho trovato che questo non era specificato nelle risposte o nei commenti, che sono tutti pertinenti e corretti, quindi ho scelto di aggiungerlo. Esplicito è meglio che implicito!

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.