Abbandonare le modifiche senza eliminare dalla cronologia


180

C'è un commit che non ha funzionato, quindi voglio abbandonarlo senza eliminarlo dalla cronologia .

Ho aggiornato da una revisione precedente e mi sono impegnato, creando così un nuovo capo.


Non ho rami, non voglio rami, voglio semplicemente continuare con la nuova testa esattamente com'è, niente di speciale, nessuna fusione, nessuna preoccupazione, continua a dimenticare quella precedente.

Non riesco a trovare il modo di farlo, e sto iniziando a credere che non possa essere fatto. Tutto quello che trovo è roba sui rami o roba sulla fusione.


1
È nel tuo repository, quindi non è stato cancellato dalla cronologia. Hai creato una nuova testa, quindi puoi continuare a fare revisioni senza l'errore. Cosa ti impedisce di andare avanti con la nuova testa?
ataylor,

Qual è la tua avversione per le filiali?
Andres Jaan Tack,

@Andres Non è esattamente avversione per i rami. Avevo solo bisogno che funzionasse senza uno stupido passo in più per crearne uno solo per chiuderlo.
o0 '.

Chiunque legga: si noti che in questo scenario è già stato creato un ramo; notare la spiegazione data in questa risposta: stackoverflow.com/a/3692607/3195477
UuDdLrLrSs

Risposte:


181

Aggiorna il tuo repository alla testa con la revisione che vuoi dimenticare, quindi usa hg commit --close-branchper contrassegnare quel ramo (anonimo) come chiuso. Quindi aggiornare alla testa del ramo che si fa vuole, e continuare a lavorare.

Puoi ancora vedere il ramo chiuso se usi l' -copzione per hg heads, ma non comparirà per impostazione predefinita e hg mergesaprà non provare a fondersi con la testa chiusa.

Sarà necessario utilizzare hg push --forcela prima volta che si spinge questa testa chiusa in un altro repository poiché in realtà si creano teste aggiuntive nel repository remoto quando si spinge. Quindi dì a Mercurial che va bene così --force. Le persone che tirano la testa chiusa non saranno disturbate da alcun avvertimento.


3
@Niall C. non funzionerà solo se lo ha contrassegnato come ramo con nome?
Suppongo

ma ... non è vero, ricevo ancora entrambe le teste elencate quando chiamo hg heads... Sto usando mercurial 1.4.3, è una funzionalità più recente?
o0 '.

2
@msarchet: AFAIK, provandolo oggi, --close-branch NON funziona per filiali anonime. Dovrebbe, ma non lo è. Spero che questo cambi in alcune versioni future di Mercurial. I rami anonimi sono molto belli, ma dovrebbero essere di prima classe come i rami nominati.
Krazy Glew il

4
@KrazyGlew: il problema è che un ramo "anonimo" è in realtà solo un secondo ramo con lo stesso nome del ramo su cui era basato. Non stai davvero cercando di chiudere il ramo (chiamato): stai cercando di scartare le modifiche che hai apportato. In altre parole, hg branchesdovrebbe comunque mostrare il nome della filiale in cui ti trovi. Invece di provare a chiudere il ramo, unisci nuovamente il ramo anonimo nel ramo originale, ignorando tutte le modifiche.
StriplingWarrior,

2
Nel mio caso, ho un ramo chiamato default (questo è standard) e un altro chiamato default / master (penso a causa del fatto che il depot remoto è effettivamente git). hg update default / master; hg commit --close-branch; hg update default ha funzionato per me.
MattD,

68

So che non vuoi lavorare con i rami in questa fase, ma è esattamente quello che hai fatto. Quando sei tornato a una versione precedente e hai commesso qualcosa che ha funzionato, hai creato un ramo - un ramo senza nome, ma comunque un ramo.


Non c'è problema a continuare semplicemente come sei e non preoccuparti di avere più teste, ma se vuoi mettere in ordine le cose in modo da non scegliere accidentalmente la testa sbagliata una volta, puoi uccidere il vecchio ramo.

C'è una buona sezione nella documentazione di Mercurial che ti guida attraverso una serie di opzioni su Potatura dei rami morti .

Penso che l'opzione migliore per te sia contrassegnare il vecchio ramo come "chiuso". Se la tua vecchia testa è la revisione "123", allora:

hg update -r 123
hg commit --close-branch -m 'Closing old branch'
hg update -C default

3
Blurgh: ho appena visto la risposta di @ Niall dopo che sono entrato. Will valuterà Niall e il mio può languire nella riserva di punti zero. :)
Nick Pierpoint,

1
Mi piace di più la tua risposta, richiede un po 'meno della terminologia di Merucrial (che per quanto posso dire sembra essere stata scelta per confondere gli utenti git)
tacaswell

8
lol è il contrario! La terminologia di mercurial è stata scelta per sembrare naturale per gli utenti svn, mentre quella di Git è confusa da morire! comunque, votando questa risposta perché include l'ultimo aggiornamento -C
Tobia,

2
Perché avete bisogno -Cdi hg update? Sembrerebbe che nessun file sarebbe stato modificato, quindi dovrebbe funzionare senza di esso.
massimo

1
per quanto ne so, non hai bisogno di una -C da nessuna parte. tuttavia, se si verificano modifiche in sospeso quando si tenta di aggiornare, verrà interrotto.
Eli Albert

21

Prima di tutto, digita:

hg heads

Immagina di avere tre teste elencate:

changeset:   223:d1c3deae6297
user:        Your name  <your@email.com>
date:        Mon Jun 09 02:24:23 2014 +0200
summary:     commit description #3

changeset:   123:91c5402959z3
user:        Your name <your@email.com>
date:        Sat Dec 23 16:05:38 2013 +0200
summary:     commit description #2

changeset:   59:81b9804156a8
user:        Your name <your@email.com>
date:        Sat Sep 14 13:14:40 2013 +0200
summary:     commit description #1

Diciamo, vuoi mantenere attiva l'ultima testa (223) e chiudere il resto.

Dovresti quindi fare come segue:

Chiudi la testa # 59

hg up -r 59
hg ci --close-branch -m "clean up heads; approach abandoned"

Chiudi testa # 123

hg up -r 123
hg ci --close-branch -m "clean up heads; approach abandoned"

Conferma le modifiche

hg push

Non dimenticare di passare alla testa destra alla fine

hg up -r 223

E hai finito.


Questo è un bel tutorial, ma i messaggi di commit di esempio sono un po 'meta. Includerei esempi migliori in modo che coloro che imparano da te possano fornire messaggi di commit migliori. Qualcosa del genere --close-branch -m "Closing branch - technique #2 abandoned in favor of technique #3".
Jason R. Coombs,

5
Inoltre, alla fine hai finito, tranne per il fatto che la tua copia di lavoro è ancora sulla testa che hai appena chiuso. Commettere un altro cambiamento sarebbe accaduto sulla testa chiusa, riaprendolo. Ti consigliamo hg up -r 223prima di apportare eventuali modifiche.
Jason R. Coombs,

@Jason R. Coombs: Giusto!
Artur Barseghyan,

secondo @Niall, e la mia esperienza proprio ora, sarà necessario hg push --force, non solo hg pushper superare l'avvertimento di spingere più teste.
craq,

1
@Artur Sono d'accordo in generale. In questo caso, di hg pushper sé non ha funzionato per me. Come consigliate di inviare le modifiche a un repository esterno se rifiuta a causa di più teste?
craq,

12

Si desidera utilizzare hg backout. Ciò rimuove le modifiche apportate dal changeset da qualunque changeset figlio.

Dai un'occhiata per una buona spiegazione. Backout mercuriale


2
Questa è esattamente la risposta giusta. Il backout aggiunge l'inverso di un changeset, annullando il funzionamento e dandoti un messaggio di commit per ricordare a te stesso perché non ti è piaciuta l'idea.
Ry4an Brase,

7
In realtà non sono d'accordo: abbandonare il lavoro su una testa e ricominciare da un buon punto di partenza sembra un modello di lavoro più pulito rispetto all'utilizzo dei backout. Soprattutto perché non è possibile eseguire il backout di più di un changeset alla volta.
Martin Geisler,

1
@Martin Geisler, bene sono d'accordo con questo in generale, ma l'OP ha dichiarato che voleva abbandonare le modifiche senza rami
msarchet,

2
@Martin Geisler sì, sono tutto per le ramificazioni, a volte solo annusando un brutto cambiamento è il migliore
msarchet,

1
potrebbe essere utile a volte, ma non era proprio quello che volevo. Grazie comunque :)
o0 '.

2

Sia le risposte di Niall che quelle di Nick sono dirette. Poiché mi ritrovo a creare molte teste penzolanti, ho finito per scrivere un alias per chiudere le teste più facilmente. Aggiungendo questo al tuo .hgrc:

[alias]
behead = !REV=$($HG id -i); $HG update $@ -q && $HG ci --close-branch -m "Closing dead head" && $HG update $REV -q

(se hai già una [alias]sezione, puoi invece aggiungerla)

Ora puoi chiudere un head in un singolo comando (e senza dover aggiornare manualmente un diverso changeset) in questo modo:

$ hg behead 123

Nota: l'alias sfrutta il fatto che gli alias mercuriali possono essere comandi di shell . Ciò significa che probabilmente funzionerà solo su UNIX, non su Windows.


2

Un'alternativa alla chiusura o alla rimozione del ramo indesiderato sarebbe quella di fonderlo in un modo che scarti totalmente i suoi effetti, ma lo lasci nella storia. Questo approccio consentirà a quelle modifiche indesiderate di propagarsi in una spinta, quindi utilizzale solo se questo è l'effetto desiderato.

Diciamo che la storia del changeset si presenta così:

1-2-3-4-5-6    
       \    
        7-8-*

ed è 5e 6che non sono più desiderati.

Puoi farlo:

hg up 8
hg merge -r 6 -t :local
hg commit ...

che creerà questo:

1-2-3-4-5-6    
       \   \
        7-8-9-*

L'aggiornamento 8assicura che tu stia lavorando alla testa desiderata nella storia, che vuoi mantenere.

I -t :localincarica hg di utilizzare la "funzione" merge chiamata locale che gli dice di ignorare le modifiche dal ramo, vale a dire, quella che non rappresentata dallo stato cartella di lavoro corrente. Maggiori informazioni .

Pertanto, i cambiamenti indesiderati 5e 6sono conservati nella storia ma non incidono su nulla di più recente.


2

Questo è un caso d'uso per l' estensione Evolve . Al momento non è in bundle con Mercurial, quindi è tecnicamente un'estensione di terze parti. Ma viene utilizzato abbastanza pesantemente da un gruppo di persone, inclusi gli sviluppatori Mercurial, è stato sviluppato molto attivamente e non va da nessuna parte.

Con l'estensione Evolve, lo fai semplicemente

hg prune -r revname

e andare avanti con la tua vita. Il cset sarà ancora lì, ma obsoleto. Non sarà visibile se non si passa l' --hiddenopzione ai comandi Mercurial e, per impostazione predefinita, non verrà inviato ai repository remoti. Anche se penso che tu possa forzarlo se davvero lo desideri.

Se il cset che stai potando ha antenati che vuoi mantenere, allora dovrai correre hg evolveper rifare le modifiche. hg evolvelo farà automaticamente. Altrimenti, non devi fare nulla.


1

Puoi clonare il tuo repository corrotto su uno nuovo senza clonare quella testa indesiderata. Quindi rimuovere il vecchio repository, spostare il clone appena creato nella posizione originale e continuare a lavorarci. Questo richiederà del tempo, ma otterrai un repository perfettamente pulito senza un segno di quella revisione indesiderata.

hg clone --rev myGoodResition myDirtyRepo myCleanRepo

1
Non è assolutamente quello che ho chiesto, scusa.
o0 '.

4
@Kristof: è uno scherzo? Rileggi la prima riga del mio post: "abbandonalo senza cancellarlo dalla storia "
o0 '.

-1

Ho riscontrato questo problema molte volte quando voglio decapitare una testa che è stata creata per errore. Voglio sempre vederlo scomparire dalla faccia della Terra.

Sulla tua copia locale, ottieni le ultime e poi:

  1. Trova l'inizio di una testa che vuoi spogliare (dove un nuovo collo inizia a diramarsi), ottieni il numero di revisione

  2. Spoglialo.


Fonte: TipsAndTricks .

Fonte: PruningDeadBranches # Using_strip .

hg --config extensions.hgext.mq= strip -n <rev>
  1. Effettua un banale aggiornamento del file (aggiungi uno spazio bianco a un file), esegui il commit e il push.

Il repository ora dovrebbe avere la testa spogliata. L'ultimo passaggio è importante poiché lo stripping non crea alcuna modifica che è possibile inviare al repository centrale. Senza l'ultimo passaggio hai solo spogliato la testa localmente.


1
Ma, spingendo non si elimina mai nulla dal repository remoto. Aggiunge sempre e solo informazioni. Se il changeset è già sul repository centrale, è necessario utilizzare l'estensione evolve o in qualche modo rimuoverlo sul server centrale stesso. Se il changeset non è già sul repository centrale, è sufficiente rimuoverlo localmente senza alcun push richiesto.
Ben
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.