Come applicare una patch git da un repository ad un altro?
-
06-09-2019 - |
Domanda
Ho due depositi, uno è il repo principale per una biblioteca, e l'altro è un progetto che utilizza tale libreria.
Se faccio una correzione al nel progetto servile, mi piacerebbe un modo semplice per applicare la patch di nuovo a monte.
La posizione del file è diverso in ogni repository.
- repo principale:
www.playdar.org/static/playdar.js
- Progetto:
playlick.com/lib/playdar.js
Ho provato ad utilizzare git format-patch -- lib/playdar.js
sul progetto playlick, e poi git am
sul repo playdar principale, ma le posizioni dei file differenti nel file di patch generato un errore.
C'è un modo semplice per applicare la patch da un dato impegnarsi su un dato file in un altro file arbitrario altrove?
Per i punti bonus, che cosa succede se il file che si desidera applicare la patch per non è in un repository git?
Soluzione
Se modificando manualmente il file di patch è fuori questione e fattibile, questo può essere fatto con le opzioni standard (disponibile in git apply
, git format-patch
e GNU patch
).
-
-p<n>
rimuoven
leader directory dai percorsi nella patch. -
Dopo l'elaborazione
-p
, antepone--directory=<root>
root
a ciascuno dei percorsi nella patch prima di applicare.
Esempio
Quindi, per il vostro esempio, di prendere una patch che in origine era il static/playdar.js
e applicarlo a lib/playdar.js
, si dovrebbe eseguire:
$ cat patch_file | git am \
-p1 \ # remove 1 leading directory ('static/')
--directory='lib/' # prepend 'lib/'
Altri suggerimenti
La patch prodotta da git format-patch
è semplicemente un testo file-- è possibile modificare le intestazioni diff in modo che esso modifica un percorso diverso.
Così, per esempio avrebbe prodotto qualcosa di simile:
diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js
Tutto quello che dovete fare è cambiare lib/playdar.js
a static/playdar.js
e quindi eseguire la patch attraverso git am"
Il cerotto deve essere leggibile dal programma di utilità di patch GNU standard per le persone che non hanno git
--- ma non eseguire format-patch
con la -M
, -C
ecc opzioni per la produzione di rinominare i patch in questo caso, perché il supporto per loro non è universale.
Supponendo che entrambi i progetti sono progetti git, che suona come sottomoduli sarebbe il misura perfetta per voi. Questo permette un progetto Git collegare in modo dinamico a un altro progetto Git, in sostanza, la cottura un repo git destra all'interno di un altro repo git, entrambi con le loro vite distinte.
In altre parole, aggiungere "pronti contro termine principale" come un modulo in "progetto". Ogni volta che si impegnano / push novità in "pronti contro termine principale", è semplicemente git pull
nuovo nel "progetto".
Per completare Henrik di rispondere , e di andare per il punto di bonus
Che cosa succede se il file che si desidera applicare la patch per non si trova in un repository git?
Se si ha accesso alle directory del file candidato per una patch proveniente da un repository git, si potrebbe prima di trasformare l'albero di directory / file in un repository git stesso! ( 'git init
': un repository git è solo un .git all'interno di una directory principale, dopo tutto)
.
Quindi è necessario impostare che repo come modulo per il progetto principale.
È possibile aggiungere un nuovo telecomando e tirare da esso. articolo con i dettagli.
$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA
Si può solo rimuovere (rinomina) temporaneamente il repository principale.
cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git
Con l'opzione --relative
per format-patch
in grado di migliorare l'astrazione (nascondere dettagli irrilevanti sul repository da cui è stata generata la patch).
[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'
ho trovato la possibilità --3way
essere richiesta quando l'applicazione della patch (per evitare errori does not exist in index
) - la vostra situazione potrebbe essere diversa. Utilizzando --directory=(...)
è probabile necessarie solo se il percorso di destinazione non è la radice del repository.
[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)
-
format-patch
creerà un file di patch per impegnarsi per il ramo attuale dal 'base'. -
La documentazione per l'opzione
--relative
sembra essere manca in alcuni casi , ma sembra funzionare in ogni caso (a partire dalla versione 2.7.4).