2009-06-22 16 views
46

Penso di conoscere già la risposta ma ho pensato di chiedere comunque:C'è un modo per rimuovere la cronologia per un singolo file in Mercurial?

Abbiamo un file che è stato aggiunto a un repository Mercurial con informazioni riservate. C'è un modo per rimuovere quel file con la sua cronologia delle modifiche senza rimuovere l'intero repo?

+0

questa risposta mi ha aiutato, anche se non "rimuove" ma converte il repository su se stesso (e perdi tutti gli ID dei changeset): http: // stackoverflow.com/a/22607889/714733 – jazzcat

risposta

22

No, non è possibile. Leggi la sezione changes that should have never been del volubile libro rosso su di esso; e in particolare la what about sensitive changes that escape comma, che contiene questo paragrafo:

Mercurial anche non fornisce un modo per fare un file o changeset completamente scomparire dalla storia, perché non è alcun modo per imporre la sua scomparsa ; qualcuno potrebbe facilmente modificare la loro copia di Mercurial a ignorare tali direttive. Inoltre, anche se Mercurial fornito una tale capacità , qualcuno che semplicemente non aveva tirato un “fare questo file sparire” di modifiche non sarebbe influenzata da esso, né sarebbe web crawler in visita al momento sbagliato, backup del disco o altri meccanismi . Infatti, nessun sistema di controllo di revisione distribuito può rendere i dati svaniscono in modo affidabile. Fornire l'illusione di tale controllo con potrebbe facilmente dare un falso senso di sicurezza a ed essere peggiore di non fornirlo affatto.

Il solito modo per annullare le modifiche impegnati è supportato da Mercurial tramite il comando backout (ancora una volta, il libro mercuriale: dealing with committed changes), ma l'informazione non scompare dal repository: dato che non si sa mai chi esattamente clonato il repository, che darebbe un falso senso di sicurezza, come spiegato sopra.

+12

Sì, è possibile: https://www.jitbit.com/alexblog/232-removing-files-from-mercurial-history/ Naturalmente, tutti voi dovete reclutare i vostri repository, ma non lo fate Perdi tutta la storia. – wrzasa

+0

Mentre questa è la risposta accettata, non è la risposta corretta. @wrzasa ha fatto riferimento alla risposta corretta nel suo commento. Ho fatto personalmente quello che l'OP ha chiesto più volte usando le informazioni da quel collegamento. – Chris

-2

hg trapianto, poi hg spellare

+0

Il file attraversa quasi l'intera cronologia delle modifiche. Puoi approfondire come utilizzare i comandi sopra riportati per eliminare la cronologia dei file dal repository lasciando intatta la cronologia delle modifiche degli altri file? –

+1

Non è possibile utilizzare il trapianto per rimuovere un singolo file da un changeset - il trapianto sa solo come spostare interi changeset da un ramo o repository all'altro (è come import hg export | hg). Vedi la mia risposta sull'estensione convert. –

58

È vero che non è possibile rimuovere facilmente un file particolare da Mercurial, nel senso che così facendo interromperà tutti gli ID changeset nel repository. Quando si modificano gli ID del changeset, tutti devono ri-clonare il repository. Vedere lo Wiki page about editing history per informazioni sulle conseguenze della modifica della cronologia in Mercurial.

Se ciò è a posto (repository interno in un'azienda), quindi dare un'occhiata allo convert extension. Può fare conversioni hg → hg e ha un argomento --filemap che può essere utilizzato per escludere i file, tra le altre cose.

+1

Vedere http://stackoverflow.com/questions/10103227/how-do-you-remove-big-files-from-history-in-mercurial per gestire un problema in una certa versione Mercurial. –

+1

Grazie a Martin, è stato salvato un repository enormemente gonfio pieno di oggetti binari compilati. Salvato il giorno! –

7

È possibile localmente, ma non globalmente, e cambia l'ID di ogni commit dopo il punto in cui è stato aggiunto il file. Affinché la modifica si attacchi, avrai bisogno di accedere a ogni singola copia del repository, in particolare a quelli che vengono tirati o spinti.

Detto questo, ho seguito la sequenza Editing History descritta nel wiki Mercurial per rimuovere un file da uno dei miei repository.Questa sequenza presuppone che la revisione 1301: 5200a5a10d8b aggiunto il file path/to/badfile.cfg, che non è stato modificato in qualsiasi revisione successiva:

  1. Abilitare l'estensione MQ nel .hgrc:

    [extensions] 
    mq = 
    
  2. Tirare modifiche recenti da monte .

    hg pull 
    
  3. importare tutto dal file aggiunta poi in MQ:

    hg qimport -r 1301:tip 
    hg qpop -a 
    
  4. rimuovere il file dal commit che ha aggiunto di esso.

    hg qpush 1301.diff 
    hg forget path/to/badfile.cfg 
    hg qrefresh 
    
  5. Convertire le patch in nuove revisioni Mercurial.

    hg qpush -a 
    hg qfinish -a 
    
  6. Premere le nuove revisioni a monte.

    hg push -f 
    
  7. Sul repository upstream e ogni singola altra copia, rimuovere le vecchie revisioni.

    hg strip 5200a5a10d8b 
    

Attenzione: Questo passaggio può distruggere l'opera, a meno che non si sta attenti. Se qualcuno ha commesso qualcosa dall'ultima volta che hai estratto l'upstream, dovrai prima ridimensionarlo prima di eseguire lo stripping. Sfortunatamente, l'estensione rebase non è utile qui; dovrai ricominciare a utilizzare MQ, convertendo i nuovi commit in patch applicate alla nuova punta.

Buona fortuna.

+0

Ho dovuto 'hg phase --secret --force 1301' prima che funzionasse come un incantesimo. –

+0

Interessante. Sembra che le fasi siano un po 'diverse, nascondendo l'intero commit invece di rimuovere un file dal commit. Inoltre, probabilmente non rimuoveranno o nasconderanno il commit per il repository upstream. – eswald

4

Può essere fatto in meno di 10 minuti. in un unico repository, anche se ci sono conseguenze.

Come: utilizzare hg convert come descritto in this excellent guide. Fondamentalmente, "converti" un repository Hg in un nuovo repository Hg, ma devi specificare un elenco di file da escludere durante la conversione. Questo è un estratto dei passaggi chiave:

Make sure all your teammates have pushed their local changes to the central repo (if any) 
Backup your repository 
Create a "map.txt" file: 

# this filemap is used to exclude specific files 
exclude "subdir/filename1.ext" 
exclude "subdir/filename2.ext" 
exclude "subdir2" 

Run this command: 
hg convert --filemap map.txt c:/oldrepo c:/newrepo 
NOTE: You have to use "forward-slash" in paths, even on windows. 
Wait and be patient 
Now you have a new repo at c:\newrepo but without the files 

Per quanto riguarda le conseguenze ...

  • tutti gli ID changeset Dopo che i file che si desidera escludere sono stati aggiunti saranno diversi
  • il nuovo " pulito "repository principale dovrà essere messo manualmente al posto di quello esistente
  • tutti i membri del team dovranno creare nuovi cloni del repository principale
  • eventuali altri servizi che si integrano con Hg potrebbero richiedere attenzione (ad es. il tracker dei problemi, un sistema di revisione del codice ecc.)
Problemi correlati