Con Mercurial, come posso "comprimere" una serie di changeset in uno prima di eseguire il push?


96

Diciamo che ho un repository Mercurial locale e uno remoto. Ora inizio a lavorare su una funzionalità. Ci lavoro e quando penso che sia finito, metto in commit il changeset. Testandolo un po 'di più, trovo che potrei migliorare ulteriormente questa funzionalità modificando qualcosa nel codice. Faccio il cambiamento e mi impegno. 20 minuti dopo, trovo che ci sia un bug in questa nuova funzionalità, quindi lo risolvo e lo impegno anche io.

Ora ho 3 changeset che vorrei davvero inviare al repository remoto come un changeset con il messaggio "Implementing feature X", per esempio.

Come posso farlo senza troppi problemi? Credo di poterlo fare con le patch, ma mi sembra un sacco di lavoro.


40
Chiaramente non spetta a me convincerti a non provare a comprimere i tuoi changeset, ma potresti considerare che metà del valore del controllo di versione sta rispondendo "perché" non solo "cosa" mesi e anni dopo. Una rappresentazione accurata di come è nata una caratteristica e in quali fasi potrebbe avere un valore futuro. Scartando sembra così ... unversioncontrolly.
Ry4an Brase

Questo porta a un'altra domanda ... Qual è la differenza tra 'histedit' e 'collapse'
sylvanaar

1
collapse fornisce un sottoinsieme delle funzionalità di histedit e histedit ha una UX molto più intuitiva.
Stefan Rusek

1
Fornisce inoltre un meccanismo per modificare il messaggio del changeset unito.
Stefan Rusek

1
@ Ry4an: In realtà, in alcuni casi la compressione / compressione aggiunge rilevanza al controllo della versione. Senza schiacciare, avrei due commit ogni giorno che non hanno nulla a che fare con funzionalità o correzioni di bug, ma servono per spostare il codice dal laptop al desktop e viceversa. Aggiungono solo rumore alla cronologia delle versioni.
John Reynolds

Risposte:


39

Che ne dici dell'estensione Collapse ?


20
Saluti dal futuro! Ho appena cercato su Google la stessa funzionalità e apparentemente al giorno d'oggi hg lo supporta immediatamente con hg rebase --collapse. Controlla il wiki hg sul comando rebase. Poiché questa domanda è il terzo risultato di ricerca complessivo e il primo su stackoverflow, ho pensato che le informazioni potessero essere utili.
a.peganz

1
Saluto anche da più lontano in futuro !! L'estensione rebase sembra essere mirata esclusivamente allo spostamento di changeset da un ramo all'altro. Sì, c'è un'opzione --collapse, ma sembra ancora essere applicabile solo quando si sposta un set di modifiche tra i rami. Vedi < mercurial-scm.org/wiki/… >
Brad Oestreicher

3
Puoi usare hg rebasecon --collapseall'interno di un singolo ramo.
UuDdLrLrSs

52

L' estensione histedit è esattamente quello che stai cercando.

hg histedit -o

o

hg histedit --outgoing

farà apparire un elenco dei changeset in uscita. Dalla lista puoi

  • Piega 2 o più changeset creando un unico changeset
  • Elimina i changeset rimuovendoli dalla cronologia
  • Riordina i changeset come preferisci.

histedit ti chiederà il nuovo messaggio di commit dei gruppi di modifiche piegati che di default sono i due messaggi con "\ n *** \ n" che li separa.

Puoi anche ottenere risultati simili usando l'estensione mq, ma è molto più difficile.

Puoi anche utilizzare l'estensione di compressione per eseguire semplicemente la piegatura, ma non fornisce un'interfaccia utente così piacevole e non fornisce un modo per modificare il messaggio di commit risultante. La modifica del messaggio di commit risultante consente anche di ripulire il messaggio finale, che è qualcosa che finisco sempre per utilizzare.


grazie, è esattamente quello di cui avevo bisogno. Sarebbe bello se potessi farlo da TortoiseHg, ma la riga di comando è abbastanza semplice.
sylvanaar

21

Sì, puoi farlo con le patch: supponiamo che il tuo lavoro sia nei changeset da 100 a 110 inclusi

  1. Crea una patch:

    % hg export -o mypatch 100:110 --git

  2. Aggiorna a 99:

    % hg update 99

  3. Applica la patch con --no-commit (altrimenti recupererai tutti i tuoi changeset):

    % hg import --no-commit mypatch

  4. Salva tutte le modifiche in una volta:

    % hg commit

  5. Ora hai due testine (110 e 111) che dovrebbero essere equivalenti in termini di file che producono nella tua directory di lavoro - magari diffonderli per sanità mentale prima di rimuovere quelli vecchi:

    % hg strip 100

OK, ora che ho spiegato tutto, sembra lungo, ma avendolo fatto un sacco di volte io stesso, non trovo che sia troppo un compito ingrato ...


1
Ottima risposta, ma c'è un prerequisito: l' estensione MQ deve essere abilitata .
Chris Kelly

Per includere modifiche anche nei file binari, assicurati di utilizzare l'opzione --git: ad esempio: "hg export -o mypatch 100: 110 --git" Per ulteriori informazioni, consulta: stackoverflow.com/a/12537738/ 367663 Mi sono preso la libertà di modificare la risposta.
Kharlos Dominguez

1
Sembra troppo complicato, perché no hg strip --keepe poi esegue il commit di tutto in un unico commit?
G. Demecki

@ G.Demecki Perché è un'operazione potenzialmente molto con perdite ..? Sebbene MQ sia eccessivo (e anche spesso sconsigliato), tranne quando si desidera un flusso di lavoro del genere.
user2864740

@ user2864740 Potresti avere ragione, perché non sono un esperto di Mercurial. Ma per impostazione predefinita, hg stripinserirà un backup nel file.hg/strip-backup/ directory. Immagino che non sia così sicuro, git reflogma fornisce comunque una sorta di salvataggio.
G. Demecki

19

Se stai usando TortoiseHg, puoi solo selezionare due revisioni (usa CTRL per selezionare quelle non successive), fare clic con il tasto destro e selezionare "Comprimi cronologia" .

Dopodiché otterrai un nuovo elenco di modifiche nella nuova intestazione a partire dalla prima modifica selezionata in precedenza, conterrà tutti gli elenchi di modifiche discendenti tra quelli selezionati.

Puoi semplicemente eliminare i vecchi elenchi di modifiche se non ne hai più bisogno: usa le estensioni MQ per questo. Di nuovo, in TortoiseHg: fai clic con il pulsante destro del mouse sulla prima lista di modifiche che deve essere spogliata con tutti i suoi discendenti, "Modifica cronologia -> Rimuovi" .


18

Il mio metodo preferito per utilizzare mq per questa piegatura è utilizzare TortoiseHg come descritto qui . Tuttavia, può essere facilmente eseguito dalla riga di comando in questo modo:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

(Potrebbe esserci un modo migliore per eseguire il passaggio qfold, ma non ne sono a conoscenza, poiché di solito uso TortoiseHg per quell'operazione.)

All'inizio sembra un po 'complicato, ma una volta che hai iniziato a usare mq, è abbastanza semplice e naturale - inoltre puoi fare ogni genere di altre cose con mq che possono essere molto utili!


4

hg collapsee hg histeditsono i modi migliori. O, piuttosto, sarebbero i modi migliori, se funzionassero in modo affidabile ... Sono riuscito histedita bloccarmi con uno stack dump entro tre minuti. Collapsenon è molto meglio.

Ho pensato di poter condividere altri due BKM:

  1. hg rebase --collapse

    Questa estensione è distribuita con Mercurial. Non ho ancora avuto problemi con esso. Potrebbe essere necessario giocare ad alcuni giochi per aggirare le hg rebaselimitazioni: in pratica, non gli piace ribasare a un antenato sullo stesso ramo, denominato o predefinito, sebbene lo consenta se si ribasano tra rami (denominati).

  2. Spostare il repository ( foo/.hg) nella directory di lavoro ( bar) e nei suoi file. Non il contrario.

Alcune persone hanno parlato della creazione di due alberi clone e della copia dei file tra di loro. O rattoppare tra di loro. Invece, è più facile spostare le .hgdirectory.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Questo funziona fintanto che i veri repository, gli .hgalberi, sono indipendenti dalla directory di lavoro e dai suoi file.

Se non sono indipendenti ...


Nel 2015, histeditè un'ottima opzione per questo compito. Non mi fido ancora di esso perché eseguo un git rebase -i, ma non si blocca .. almeno le versioni più recenti ti lasceranno su un ramo temporaneo se qualcosa va storto, quindi l'unica volta che i changeset saranno rimossi è dopo il commit del nuovo ramo.
user2864740

2

Non ho mai usato Mercurial, ma suona molto simile a ciò di cui parlava Martin Fowler sul suo blog non molto tempo fa:

http://martinfowler.com/bliki/MercurialSquashCommit.html


Sembra più che complicato, ma grazie per il collegamento. Onestamente, spero in qualche estensione magica che faccia proprio quello che voglio, come il recupero e il trapianto fatto con le modifiche apportate e selezionate.
Lucas

0

Perché non solo hg strip --keepcomando?

Quindi puoi eseguire il commit di tutte le modifiche come un unico commit.


@Strawberry non fornisce una risposta ?? Pensa che risponda perfettamente alla domanda dell'autore. Puoi approfondire il tuo punto?
G. Demecki

È storia antica, quindi ritratterò l'osservazione, ma la risposta Approvata sembra un riferimento più autorevole.
Fragola

1
@Strawberry In effetti è un filo antico. Ma la risposta accettata è obsoleta, perché Mercurial non ha più bisogno di un'estensione di terze parti separata per questo lavoro.
G. Demecki

0

HistEdit farà quello che vuoi, ma probabilmente è eccessivo. Se l'unica cosa di cui hai bisogno è piegare insieme alcuni changeset, l' estensione Collapse farà il lavoro.


1
anche se fornisce un'interfaccia utente molto più facile da usare e da capire, che è più che una ragione sufficiente per usarlo, ma fornisce anche un meccanismo per modificare il messaggio del changeset unito, che è un'altra cosa che voglio sempre fare quando lo faccio unire i changeset.
Stefan Rusek

E il problema di capire solo l'interfaccia utente è che non si capisce davvero .. Comunque, per il passato mentre histedit permetteva di cambiare i "messaggi", così come di cambiare i messaggi quando si "ripiegavano". L'histedit è perfetto; semmai, l'estensione del collasso è poco utile.
user2864740

0

Supponiamo di avere due commit inediti THISe THATin Mercurial e che si vogliano unire in un unico commit al THISpunto ::

... --> THIS --> ... --> THAT --> ... --> LAST

Verifica che i tuoi commit non siano pubblicati:

$ hg glog -r "draft() & ($THIS | $THAT)"

Aggiorna per LASTeseguire il commit:

$ hg up

e importa commit fino a THISMQ:

$ hg qimport $THIS::.

Annulla l'applicazione di tutte le patch e applica solo prima THIS:

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Unisciti a THAT:

$ hg qfold $THATNAME

NOTA Per trovare il nome THATNAMEutilizzare:

$ hg qseries

Applica tutte le patch e spostale nella cronologia del repository:

$ hg qpush -a
$ hg qfinish -a

Il mio post sul blog sull'argomento è Unire due commit in Mercurial .


0

Sì, strip --keepfunziona per la domanda dell'autore. Ma era leggermente diverso dagli altri, ad esempio, se hai la versione da 1 a 30 ma vuoi solo comprimere la versione 12-15. Altre soluzioni funzionano ma non strip --keep.

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.