¿Hay alguna manera de eliminar el historial de un solo file en Mercurial?

Creo que ya sé la respuesta a esto, pero pensé en preguntar de todos modos:

Tenemos un file que se agregó a un repository de Mercurial con información sensible. ¿Hay alguna forma de eliminar ese file junto con su historial de cambios sin eliminar todo el repository?

No, no puedes. Lea los cambios que nunca deberían haber sido la sección del libro rojo mercurial al respecto; y particularmente, ¿qué pasa con los cambios sensibles que escapan a la subsección, que contiene este párrafo:

Mercurial tampoco proporciona una forma de hacer que un file o set de cambios desaparezca completamente del historial, porque no hay forma de imponer su desaparición; alguien podría modificar fácilmente su copy de Mercurial para ignorar tales directivas. Además, incluso si Mercurial proporcionara tal capacidad, alguien que simplemente no hubiera sacado un set de cambios "make this file disappear" no se vería afectado por él, ni los rastreadores web lo visitarían en el momento equivocado, copys de security de disco u otros mecanismos . De hecho, ningún sistema de control de revisión distribuido puede hacer que los datos desaparezcan de manera confiable. Proporcionar la ilusión de dicho control podría fácilmente dar una falsa sensación de security y ser peor que no proporcionarlo en absoluto.

La forma habitual de revertir los cambios confirmados es respaldada por mercurial a través del command de backout (de nuevo, libro mercurial: trata de cambios comprometidos ) pero la información no desaparece del repository: ya que nunca se sabe quién clonó exactamente su repository, eso daría una falso sentido de security, como se explicó anteriormente.

Es correcto que no se puede eliminar fácilmente un file en particular de Mercurial en el sentido de que hacerlo interrumpirá todos los ID de los sets de cambios en su repository. Cuando cambia los ID del set de cambios, todos tienen que volver a clonar el repository. Consulte la página Wiki sobre el historial de edición para get información sobre las consecuencias de modificar la historia en Mercurial.

Si eso está bien para usted (repository interno en una empresa), entonces eche un vistazo a la extensión de conversión . Puede hacer conversiones hg → hg y tiene un argumento –filemap que puede usarse para excluir files, entre otras cosas.

Es posible localmente, pero no globalmente, y cambia el ID de cada confirmación después del punto en el que se agregó el file. Para que el cambio se mantenga, necesitarás acceso a cada copy del repository, especialmente las que se extraen o se envían.

Dicho esto, he seguido la secuencia de Editar Historial descrita en la wiki de Mercurial para eliminar un file de uno de mis repositorys. Esta secuencia supone que la revisión 1301: 5200a5a10d8b agregó la path/to/badfile.cfg del file path/to/badfile.cfg , que no se modificó en ninguna revisión posterior:

  1. Habilite la extensión MQ en su .hgrc :

     [extensions] mq = 
  2. Tire de los cambios recientes desde la parte superior.

     hg pull 
  3. Importe todo desde la adición del file hacia adelante en MQ:

     hg qimport -r 1301:tip hg qpop -a 
  4. Elimine el file de la confirmación que lo agregó.

     hg qpush 1301.diff hg forget path/to/badfile.cfg hg qrefresh 
  5. Convierta los parches en nuevas revisiones de Mercurial.

     hg qpush -a hg qfinish -a 
  6. Empuje las nuevas revisiones aguas arriba.

     hg push -f 
  7. En el repository en sentido ascendente y en cada otra copy, elimine las revisiones anteriores.

     hg strip 5200a5a10d8b 

Advertencia : este paso puede destruir el trabajo, a less que tenga cuidado. Si alguien ha cometido algo desde la última vez que sacó de la stream ascendente, tendrá que volver a calcular ese trabajo antes de pelar. Desafortunadamente, la extensión de rebase no es útil aquí; tendrá que volver a usar MQ, convirtiendo los nuevos commit en parches que aplique en el nuevo consejo.

Buena suerte.

Se puede hacer en less de 10 min. en un único repository, aunque hay consecuencias.

Cómo: use hg convert como se describe en esta excelente guía . Básicamente, "convierte" un repository de Hg en un nuevo repository de Hg, pero puede especificar una list de files para excluir durante la conversión. Este es un extracto de los pasos key:

 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 

En cuanto a las consecuencias …

  • todos los ID del set de cambios después de agregarse los files que desea excluir serán diferentes
  • el nuevo repository principal "limpio" tendrá que ponerse manualmente en lugar del existente
  • todos los miembros del equipo tendrán que hacer nuevos clones del repository principal
  • cualquier otro service que se integre con Hg puede requerir atención (por ejemplo, el rastreador de problemas, un sistema de revisión de códigos, etc.)

hg transplant, luego hg strip