2014-10-24 13 views
9

Io uso il seguente comando per applicare una patch in Mercurial, senza commettere è:Come applicare più patch usando la linea di comando hg quando ci sono già modifiche non confermate?

hg import patch.diff --no-commit 

E le grandi opere, se cerco di applicare diverse patch in una sola volta in questo modo:

hg import patch1.diff --no-commit 
hg import patch2.diff --no-commit 
... 

I questo messaggio di errore dopo il secondo commettere:

abort: uncommitted changes 

Se faccio esattamente lo stesso in SourceTree (per applicare la patch1 poi cerotto 2 e scegli "Modifica file di lavoro") funziona: le due patch vengono applicate sulla copia di lavoro, le modifiche da patch1 e patch2 combinate/piegate insieme.

Come fare lo stesso utilizzando la riga di comando hg?

risposta

10

Questo è il comportamento che è stato progettato dagli autori Mercurial: immagina di avere modifiche "non eseguite manualmente" in una copia funzionante, non vorremmo che hg import applichi automaticamente la patch e impegni entrambe le modifiche e la patch cambia con un messaggio di registro errato ed entrambe le modifiche sono impigliate insieme.

Questo è il motivo per il hg help import dice:

Because import first applies changes to the working directory, import will 
abort if there are outstanding changes. 

Il comando di importazione è più per l'importazione di modifiche (con metedata quando i dati provengono da hg export) di patch solo applicando. Se si dispone delle proprie modifiche nella copia di lavoro, ad esempio, è possibile utilizzare ancora hg import --bypass e non si verificherà alcun errore perché il commit viene applicato direttamente al repository e non alla copia di lavoro. (Nota: ma se commetti solo le tue modifiche, otterrai due teste, che dovrai unire .. :-).

Una soluzione con la riga di comando per sistemi Unix consiste nell'utilizzare il comando patch anziché in hg import perché non verrà eseguita alcuna verifica delle modifiche locali. Ad esempio,

for i in 1 2 etc. 
do 
    patch -p1 < patch$i.diff 
done 
hg commit ... 

Per i non-Unix-sistemi è possibile anche avere una soluzione Mercurial pura installando l'estensione shelve, consentendo nel file di configurazione globale (mercurial.ini), e quindi utilizzare shelve per gestire le unioni un cerotto dopo l'altro:

hg import --no-commit patch1.diff 
hg shelve 
hg import --no-commit patch2.diff 
hg unshelve 
etc. 

Se mai si sarebbe verificato un conflitto, shelve lo identifica e che avrebbe dovuto risolvere poi dire shelve che è risolto con l'opzione --continue.

Spero che possa essere d'aiuto.

+0

Chi 'comando patch': io non ho queste utilità nella mia cartella mercuriale (finestre), stai parlando' hg patch'? Se è così, l'ho già provato prima di fare questa domanda SO e ho appena riportato lo stesso messaggio di errore di "hg import" – tigrou

+0

Sembra un'utility 'Linux', forse l'installazione di' cygwin' lo renderà funzionante. – tigrou

+0

Non mi sono reso conto che non stavate usando Unix, sì 'patch' è un'utilità Unix. Puoi: usare una versione di Cygwin, usare la copia come hai detto, o penso che tu possa avere una soluzione "puro-hg", la aggiungerò alla mia risposta ..;) –

4

Ecco cosa ha funzionato per me (Soluzione Windows), idea fu afferrato da Christophe Muller risposta:

copy /b "patch01.diff" + "patch02.diff" + ... + "patchXX.diff" "all.diff" 

hg import "all.diff" --no-commit 

Semplicemente concatenare tutte le patch insieme (come un unico grande file) poi applicarlo.

2

Una possibile soluzione è utilizzare Mercurial Queues (nota: sembra che questa estensione sia "spesso considerata per la deprecazione", ma non è ancora deprecata e viene preinstallata con Mercurial).

Se non si è già utilizzato MQ, è molto utile se un po 'complesso. Ma permette effettivamente di creare code di patch, che possono essere uniti, spuntato, ri-ordinato, ecc

Si potrebbe usarlo per aiutare a risolvere il problema in questo modo:

:: if you don't already have MQ initialised for the repo, do so 
hg init --mq 

:: import the patches you want as queue entries 
hg qimport -P patch1.diff 
hg qimport -P patch2.diff 
hg qimport -P patch3.diff 

L'opzione -P spinge le modifiche mentre le importi, il che significa che stai verificando efficacemente che si applicano correttamente. Quando avete tutte le patch importato in MQ, tutti loro (in modo che nessuno si applicano e si è di nuovo al punto di partenza) pop, e li piega in un nuovo, patch di combinata:

:: go back to no patches applied, and create a new patch at the front of the queue 
hg qpop --all 
hg qnew -m "Your planned commit message" combined_patches 
:: fold the named patches into the current one 
hg qfold patch1 patch2 patch3 

Poi, se si 're felice con la patch risultante, basta convertirlo in un insieme di modifiche 'reale':

:: convert combined_patches into a "real" changeset 
hg qfinish combined_patches 
+0

Mercurial Queues è distribuito con Mercurial, ma non abilitato per impostazione predefinita. Nel caso ti stia chiedendo perché è spesso considerato per la deprecazione: http://gregoryszorc.com/blog/2014/06/23/please-stop-using-mq/ – Mathiasdm

+0

@Mathiasdm: Ah, devo averlo abilitato io allora :) - e sì, stavo proprio leggendo quell'articolo proprio ora. – icabod