Qual è il modo più semplice per eseguire il commit e il push di un singolo file lasciando solo altre modifiche?

StackOverflow https://stackoverflow.com/questions/125272

Domanda

Sono relativamente nuovo su Mercurial e il mio team lo sta provando in questo momento in sostituzione di Subversion.

Come posso eseguire il commit e il push di un singolo file in un altro repository lasciando senza modifiche altre modifiche nella mia directory di lavoro (o almeno non trasferite nell'altro repository)?

Questo accade per noi con le migrazioni del database. Vogliamo affidare la migrazione al controllo del codice sorgente in modo che un DBA possa visualizzarlo e modificarlo mentre stiamo lavorando alle modifiche del codice per accompagnare quella migrazione del database. Le modifiche non sono ancora pronte per essere implementate, quindi non vogliamo eliminarle tutte.

In sovversione, farei semplicemente:

svn add my_migration.sql  
# commit only the migration, but not the other files I'm working on
svn commit -m "migration notes" my_mygration.sql

e continua a lavorare localmente.

Questo non funziona con Mercurial come quando lo sto spingendo verso l'altro repository, se ci sono cambiamenti che non ho abbattuto, vuole che li abbassi, li unisca e commetta che si uniscono al repository. I commit dopo l'unione non ti consentono di omettere i file, quindi ti costringe a impegnare tutto nel tuo repository locale.

La cosa più semplice che riesco a capire è di eseguire il commit del file nel mio repository locale, clonare il mio repository locale, recuperare qualsiasi nuova modifica dal repository reale, unirli e commetterli in tale unione, e questi spingono fuori le mie modifiche.

/ p>

hg add my_migration.sql 
hg commit -m "migration notes" my_migration.sql 
cd ..
hg clone project project-clone
cd project-clone
hg fetch http://hg/project
hg push  http://hg/project

Funziona, ma sembra che mi manchi qualcosa di più semplice, un modo per dire a Mercurial di ignorare i file già nella mia directory di lavoro, fare semplicemente l'unione e inviare i file. Ho il sospetto che le code mercuriali possano farlo, ma non ho ancora sviluppato completamente mq.

È stato utile?

Soluzione

Esiste una funzione Mercurial che implementa comandi shelve e unshelve, che ti danno un modo interattivo per specificare le modifiche da archiviare fino a un momento successivo: Shelve .

Quindi puoi hg shelve e hg unshelve per archiviare temporaneamente le modifiche. Ti consente di lavorare su " patch hunk " livello per scegliere e scegliere gli oggetti da scartare. Sembra che non abbia archiviato un file elencato per l'aggiunta, ma solo i file già presenti nel repository con modifiche.

È incluso in Mercurial come "estensione" il che significa semplicemente che devi abilitarlo nel tuo file hg config.


Note per versioni davvero vecchie di Mercurial (prima che fosse incluso lo scaffale - questo non è più necessario):

Non ho visto grandi istruzioni per l'installazione con alcuni googling, quindi ecco le cose combinate che ho usato per farlo funzionare:

Ricevilo con:

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve

L'unico file (attualmente) nel progetto è il file hgshelve.py.

Modifica il tuo ~ / .hgrc per aggiungere l'estensione shelve, indicando dove hai clonato il repository:

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py

Altri suggerimenti

Sono passati quasi 2 anni da quando ho posto inizialmente questa domanda. Lo farei diversamente ora (come ho detto in un commento sopra la domanda sopra). Quello che farei ora sarebbe invece eseguire il commit delle mie modifiche su un file nel mio repository locale (puoi usare l'estensione del record hg per eseguire solo il commit di pezzi di un file):

hg commit -m "commit message" filename

Quindi spegni.

hg push

Se c'è un conflitto perché sono state apportate altre modifiche al repository che devo unire prima, aggiornerei alla revisione del genitore (visto con " hg genitori -r. " se non sai cosa lo è), commetto le mie altre modifiche lì quindi ho 2 teste. Quindi ripristina il commit del file singolo originale e tira / unisci le modifiche in quella versione. Quindi estrai le modifiche con

hg push --rev .

Per eliminare solo il singolo file e l'unione di quella revisione. Quindi puoi unire le due teste che hai localmente.

In questo modo elimina la roba di mq e il potenziale per gli hunk rifiutati e tiene traccia di tutto dal controllo del codice sorgente. Puoi anche " hg strip " revisioni se successivamente decidi di non volerlo.

tl; dr: la mia spiegazione originale sembra complicata, ma spero che spieghi completamente come usare una coda di patch. Ecco la versione breve:

$ hg qnew -m "migration notes" -f migration my_migration.sql
$ hg qnew -f working-code
# make some changes to your code
$ hg qrefresh # update the patch with the changes you just made
$ hg qfinish -a # turn all the applied patches into normal hg commits

Mercurial Queues rende questo genere di cose un gioco da ragazzi e rende possibile una manipolazione più complessa dei changeset. Vale la pena imparare.

In questa situazione, probabilmente vorrai salvare ciò che è nella directory corrente prima di annullare le modifiche:

# create a patch called migration containing your migration
$ hg qnew -m "migration notes" -f migration.patch my_migration.sql
$ hg qseries -v # the current state of the patch queue, A means applied
0 A migration.patch
$ hg qnew -f working-code.patch # put the rest of the code in a patch
$ hg qseries -v
0 A migration.patch
1 A working-code.patch

Ora facciamo qualche lavoro aggiuntivo sul codice di lavoro. Continuerò a fare qseries solo per essere esplicito, ma una volta creato un modello mentale di code di patch, non dovrai continuare a guardare l'elenco.

$ hg qtop # show the patch we're currently editing
working-code.patch
$ ...hack, hack, hack...
$ hg diff # show the changes that have not been incorporated into the patch
blah, blah
$ hg qrefresh # update the patch with the changes you just made
$ hg qdiff # show the top patch's diff

Poiché ora tutto il tuo lavoro viene salvato nella coda delle patch, puoi annullare l'applicazione di tali modifiche e ripristinarle dopo aver inserito le modifiche remote. Normalmente per non applicare tutte le patch, basta fare hg qpop -a . Solo per mostrare l'effetto sulla coda di patch, li espellerò uno alla volta.

$ hg qpop # unapply the top patch, U means unapplied
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qtop
migration.patch
$ hg qpop
$ hg qseries -v
0 U migration.patch
1 U working-code.patch

A questo punto, è come se non ci fossero cambiamenti nella tua directory. Esegui hg fetch . Ora puoi riaccendere le modifiche alla coda delle patch e unirle in caso di conflitti. Questo è concettualmente in qualche modo simile al rebase di Git.

$ hg qpush # put the first patch back on
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qfinish -a # turn all the applied patches into normal hg commits
$ hg qseries -v
0 U working-code.patch
$ hg out
migration.patch commit info... blah, blah
$ hg push # push out your changes

A questo punto, hai eliminato la migrazione mantenendo le altre modifiche locali. Le altre modifiche si trovano in una patch nella coda. Faccio la maggior parte del mio sviluppo personale usando una coda di patch per aiutarmi a strutturare meglio le mie modifiche. Se vuoi sbarazzarti della coda di patch e tornare a uno stile normale dovrai esportare le tue modifiche e reimportarle in " normal " Mercurial.

$ hg qpush
$ hg qseries -v
0 A working-code.patch
$ hg export qtip > temp.diff
$ rm -r .hg/patches # get rid of mq from the repository entirely
$ hg import --no-commit temp.diff # apply the changes to the working directory
$ rm temp.diff

Sono estremamente dipendente dalle code di patch per lo sviluppo e mq è una delle implementazioni più belle in circolazione. La capacità di apportare più modifiche contemporaneamente migliora davvero la concentrazione e la pulizia dei tuoi impegni. Ci vuole un po 'per abituarsi, ma si abbina incredibilmente bene con un flusso di lavoro DVCS.

Un'altra opzione se non si desidera fare affidamento sulle estensioni è quella di mantenere localmente un clone del repository upstream che si utilizza solo per questo tipo di attività di integrazione.

Nel tuo esempio, puoi semplicemente estrarre / unire la modifica nel repository di integrazione / upstream e inviarla direttamente al server remoto.

Quello che uso generalmente è usare per eseguire il commit di un singolo file:

 hg commit -m "commit message" filename

Nel caso successivo, ho un conflitto di unione e non sono ancora pronto per eseguire il commit delle mie modifiche, segui questi passaggi:

1) Crea un file patch.

hg diff > changes.patch

2) Ripristina tutte le modifiche non confermate in sospeso, solo dopo aver verificato il file di patch.

hg revert --all

3) Tirare, aggiornare e unire all'ultima revisione

hg pull -u
hg merge
hg commit -m "local merge"

4) Ora importa semplicemente la patch e ottieni le modifiche.

hg import --no-commit changes.patch

Ricorda di usare il flag -no-commit per confermare automaticamente le modifiche.

Dato che hai detto più facilmente, uso spesso hg commit -i (--interactive) anche quando eseguo il commit di interi file. Con --interactive puoi semplicemente selezionare i file che desideri piuttosto che digitare i loro interi percorsi nella riga di comando. Come bonus aggiuntivo puoi anche includere / escludere selettivamente blocchi all'interno dei file.

E poi solo hg push per inviare il commit appena creato.

Ho aggiunto maggiori dettagli sull'uso di hg commit --interactive in questa risposta: https: // stackoverflow .com / a / 47931672/255961

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top