Posso ottenere un output compatibile con patch da git-diff?


160

Sto facendo qualcosa di molto semplice sbagliato. Sto cercando di preparare un normale file patch, quindi posso riapplicare alcune modifiche:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

Con something_here blank funziona quasi, ma i nomi dei file non sono corretti. Penso che mi sto perdendo qualche opzione.

Nella vita reale, farò un'unione dopo il checkout, quindi la patch potrebbe fallire lì, ma vedi cosa sto arrivando.

Modifica La mia colpa qui per aver fatto la domanda sbagliata. La vera domanda è: voglio salvare le mie modifiche, fare un'unione e riapplicare le modifiche, se possibile? L'ho chiesto nel modo sbagliato perché sono abituato a usare la patch per risolvere questo tipo di problemi e git diffsembrava che fosse quello che voleva che facessi.

Il commento di Charles Bailey ebbe la risposta giusta. Per me, git-apply è la cosa giusta da fare (git-stash sembra più pesante di quello di cui ho bisogno e il rebasing e i bundle sono decisamente oltre il mio attuale livello di abilità.) Accetterò la risposta che Charles ha dato (perché tu non posso accettare un commento). Grazie per tutti i suggerimenti.

Modifica, 6 anni dopo Come tutti sanno l'argomento, ho sopravvalutato la difficoltà di git stash. Praticamente ogni giorno, userò la seguente sequenza:

$ git stash
$ git merge
$ git stash pop

8
C'è qualche motivo che desideri specificamente utilizzare patchanziché git apply?
CB Bailey

3
E anche allora, hai davvero bisogno di patch piuttosto che qualcosa di simile git stasho altri strumenti git?
CB Bailey

3
Dopo la modifica, penso che git stashsia la soluzione più semplice per quello che stai cercando di fare, ma ci sono molti approcci che funzionano.
CB Bailey

1
@Malvolio: In effetti lo è, non devi nemmeno pensare a un nome di file temporaneo per memorizzare la tua patch.
CB Bailey

4
@Charlse, a volte è necessario inviare una patch a qualcuno senza l'intero repository git. Ad esempio se si utilizza git-svn.
Elazar Leibovich,

Risposte:


139

Se vuoi usare la patch devi rimuovere i a/ b/prefissi che git usa di default. Puoi farlo con l' --no-prefixopzione (puoi anche farlo con l' -popzione patch ):

git diff --no-prefix [<other git-diff arguments>]

Di solito, però, è più facile usare direttamente git diffe poi usare l'output per alimentare git apply.

Il più delle volte cerco di evitare l'uso di patch testuali. Di solito uno o più commit temporanei combinati con rebase git stashe i bundle sono più facili da gestire.

Per il tuo caso d'uso penso che stashsia il più appropriato.

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patche poigit checkout master patch -p0 < diff.patch
Natim il

1
@Natim Per la massima sicurezza, consiglierei di utilizzare patch --dry-run < diff.patchprima di emettere l'ultimo comando.
ᴠɪɴᴄᴇɴᴛ

1
@ ᴠɪɴᴄᴇɴᴛ quale sarebbe il vantaggio di farlo? Dato che stiamo usando git, è improbabile che perdiamo qualcosa, no?
Natim,

1
@Natim Come ho detto, solo per la massima sicurezza, non è necessario annullare nulla in caso di errore. Stavo anche pensando alle persone che leggono questo e vogliono usarlo patchal di fuori di git (magari usando un file patch generato da diff) in un caso d'uso più generale.
ᴠɪɴᴄᴇɴᴛ

Per includere nuovi file nella patch è necessario includere anche "git diff --no-prefix --cached" nella patch. Forse c'è un modo migliore?
Jamshid

219

Usa solo -p1: dovrai comunque usare -p0il --no-prefixcaso, così puoi semplicemente tralasciare --no-prefixe usare -p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

1
Se ti stai chiedendo il perché, l'uomo documenti lo riassume bene - fonte .
tutuDajuju,

3
Questo non funzionerà con i nomi; git diffgenera una linea che patchignora. git applyè la strada da percorrere.
hraban

17

I diff git hanno un segmento di percorso aggiuntivo anteposto ai percorsi dei file. Puoi eliminare questa voce nel percorso specificando -p1 con patch, in questo modo:

patch -p1 < save.patch

10
  1. Salvo il diff della directory corrente (compresi i file non registrati) rispetto all'attuale HEAD.
  2. Quindi è possibile trasportare il save.patchfile ovunque (compresi i file binari).
  3. Sul tuo computer di destinazione, applica la patch usando git apply <file>

Nota: è diff anche i file attualmente in scena.

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

Hahaha. È divertente. Ho fatto questa domanda quasi quattro anni fa e il modo in cui l'ho fatto si è evoluto, ma se ieri mi avessi chiesto come farlo, avrei dato la tua risposta e detto di averlo ottenuto dalle risposte a questa domanda. (In realtà probabilmente userei un bare git diff > save.patche git checkout .invece di un reset, ma sì ...
Malvolio,

Oh, non ho notato che ha 4 anni: P. A proposito, il reset è solo per dimostrare che funziona .. Inoltre non vedo nessuno usare git applyo rendere il diff rilevante per il tuo stato e il puntatore all'ultimo commit disponibile. Fare semplicemente git diffnon ha fatto nulla
Matej,

Sì, ora mi chiedo come ho scoperto git apply. Il problema git diffè (penso) dall'uso git reset: le relazioni tra repository, indice e area di lavoro sono il problema.
Malvolio,

8

Un trucco utile per evitare di creare file patch temporanei:

git diff | patch -p1 -d [dst-dir]

Esattamente quello che volevo. Funziona perfettamente anche con gli stash! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland,
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.