Accidentalmente cometí un archivo no deseado ( filename.orig
al resolver una fusión) en mi repositorio hace varias confirmaciones, sin que me diera cuenta hasta ahora. Quiero eliminar completamente el archivo del historial del repositorio.
¿Es posible reescribir el historial de cambios de manera que filename.orig
nunca se haya agregado al repositorio en primer lugar?
git
git-filter-branch
git-rewrite-history
git-rm
Grant Limberg
fuente
fuente
Respuestas:
No use esta receta si su situación no es la descrita en la pregunta. Esta receta es para arreglar una mala fusión y reproducir tus buenas confirmaciones en una fusión fija.
Aunque
filter-branch
hará lo que quiera, es un comando bastante complejo y probablemente elegiría hacerlogit rebase
. Probablemente sea una preferencia personal.filter-branch
puede hacerlo en un solo comando, un poco más complejo, mientras que larebase
solución está realizando las operaciones lógicas equivalentes paso a paso.Prueba la siguiente receta:
(Tenga en cuenta que en realidad no necesita una bifurcación temporal, puede hacerlo con un 'CABEZAL separado', pero debe tomar nota de la identificación de confirmación generada por el
git commit --amend
paso para suministrar algit rebase
comando en lugar de usar la bifurcación temporal nombre.)fuente
git rebase -i
sería un más rápido y aún así de fácil? $ git rebase -i <sh1-of-merge> Marque el correcto como "editar" $ git rm somefile.orig $ git commit --amend $ git rebase --continue Sin embargo, por alguna razón, todavía tengo ese archivo en algún lugar el último vez que hice eso. Probablemente falta algo.git rebase -i
es muy útil, especialmente cuando tiene que realizar varias operaciones de rebase-y, pero es un dolor describir con precisión cuando no está apuntando sobre el hombro de alguien y puede ver lo que está haciendo con su editor. Uso vim, pero no todos estarían contentos con: "ggjcesquash <Esc> jddjp: wq" e instrucciones como "Mueva la línea superior después de la segunda línea actual y cambie la primera palabra en la línea cuatro a 'editar' ahora guarde y dejar de fumar "parece rápidamente más complejo que los pasos reales. Normalmente terminas con algunas--amend
y--continue
acciones, también.Introducción: tienes 5 soluciones disponibles
El cartel original dice:
Hay muchas formas diferentes de eliminar completamente el historial de un archivo de git:
En el caso del póster original, enmendar el commit no es realmente una opción en sí misma, ya que luego realizó varios commits adicionales, pero en aras de la integridad, también explicaré cómo hacerlo, para cualquier otra persona que solo quiera para modificar su compromiso anterior.
Tenga en cuenta que todas estas soluciones implican alterar / reescribir el historial / confirmaciones de una manera u otra, por lo que cualquier persona con copias antiguas de las confirmaciones tendrá que hacer un trabajo adicional para volver a sincronizar su historial con el nuevo historial.
Solución 1: compromisos de modificación
Si accidentalmente realizó un cambio (como agregar un archivo) en su confirmación anterior, y no desea que el historial de ese cambio ya exista, simplemente puede modificar la confirmación anterior para eliminar el archivo:
Solución 2: restablecimiento completo (posiblemente más una rebase)
Al igual que la solución n. ° 1, si solo desea deshacerse de su confirmación anterior, también tiene la opción de simplemente hacer un restablecimiento completo a su padre:
Ese comando restablecerá su rama a la primera confirmación principal anterior .
Sin embargo , si, como el póster original, ha realizado varias confirmaciones después de la confirmación a la que desea deshacer el cambio, aún puede usar restablecimientos duros para modificarlo, pero hacerlo también implica el uso de un rebase. Estos son los pasos que puede seguir para modificar una confirmación más atrás en el historial:
Solución 3: Rebase no interactiva
Esto funcionará si solo desea eliminar una confirmación del historial por completo:
Solución 4: bases interactivas
Esta solución le permitirá lograr lo mismo que las soluciones n. ° 2 y n. ° 3, es decir, modificar o eliminar confirmaciones más atrás en el historial que su confirmación anterior inmediata, por lo que la solución que elija utilizar dependerá de usted. Los rebases interactivos no son adecuados para rebases de cientos de commits, por razones de rendimiento, por lo que usaría rebases no interactivos o la solución de ramificación de filtro (ver más abajo) en ese tipo de situaciones.
Para comenzar el rebase interactivo, use lo siguiente:
Esto hará que git rebobine el historial de confirmación al padre de la confirmación que desea modificar o eliminar. Luego le presentará una lista de las confirmaciones rebobinadas en orden inverso en cualquier editor que git esté configurado para usar (esto es Vim por defecto):
La confirmación que desea modificar o eliminar estará en la parte superior de esta lista. Para eliminarlo, simplemente elimine su línea en la lista. De lo contrario, reemplace "pick" con "edit" en la 1ª línea, así:
A continuación, ingrese
git rebase --continue
. Si elige eliminar el compromiso por completo, entonces todo lo que necesita hacer (aparte de la verificación, consulte el paso final para esta solución). Si, por otro lado, desea modificar el compromiso, entonces git volverá a aplicar el compromiso y luego pausará el rebase.En este punto, puede eliminar el archivo y modificar la confirmación, luego continuar con el rebase:
Eso es. Como paso final, tanto si modificó el commit como si lo eliminó por completo, siempre es una buena idea verificar que no se realizaron otros cambios inesperados en su rama al diferirlo con su estado antes del rebase:
Solución 5: Filtrar ramas
Finalmente, esta solución es mejor si desea eliminar por completo todos los rastros de la existencia de un archivo del historial, y ninguna de las otras soluciones está a la altura de la tarea.
Eso eliminará
<file>
de todas las confirmaciones, comenzando desde la confirmación raíz. Si, en cambio, solo desea reescribir el rango de confirmaciónHEAD~5..HEAD
, puede pasarlo como un argumento adicionalfilter-branch
, como se señala en esta respuesta :Nuevamente, una vez que
filter-branch
se completa, generalmente es una buena idea verificar que no haya otros cambios inesperados al diferenciar su rama con su estado anterior antes de la operación de filtrado:Alternativa de filtro-rama: BFG Repo Cleaner
He oído que la herramienta BFG Repo Cleaner se ejecuta más rápido que
git filter-branch
, por lo que es posible que también desee comprobar eso como una opción. Incluso se menciona oficialmente en la documentación de rama de filtro como una alternativa viable:Recursos adicionales
fuente
filter-branch
Causa recalcular los hashes? Si un equipo trabaja con un repositorio donde se debe filtrar un archivo grande, ¿cómo lo hacen para que todos terminen con el mismo estado del repositorio?Si no ha cometido nada desde entonces, solo
git rm
el archivo ygit commit --amend
.Si usted tiene
pasará por cada cambio de
merge-point
aHEAD
, borrará filename.orig y reescribirá el cambio. Usar--ignore-unmatch
significa que el comando no fallará si por alguna razón filename.orig falta en un cambio. Esa es la forma recomendada de la sección de Ejemplos en la página del comando man git-filter-branch .Nota para usuarios de Windows: la ruta del archivo debe usar barras diagonales
fuente
git-filter-branch
parece dar la primera.filter-branch
"
y no'
cuando use Windows, o recibirá un error de "mala revisión" redactado de manera inútil.Esta es la mejor manera:
http://github.com/guides/completely-remove-a-file-from-all-revisions
Solo asegúrese de hacer una copia de seguridad de las copias de los archivos primero.
EDITAR
La edición de Neon desafortunadamente fue rechazada durante la revisión.
Vea la publicación de Neons a continuación, ¡puede contener información útil!
Por ejemplo, para eliminar todos los
*.gz
archivos comprometidos accidentalmente en el repositorio de git:¿Eso todavía no funcionó para mí? (Actualmente estoy en git versión 1.7.6.1)
No estoy seguro de por qué, ya que solo tenía UNA rama maestra. De todos modos, finalmente conseguí que mi repositorio de git se limpiara realmente al ingresar a un nuevo repositorio de git vacío y vacío, por ejemplo
(¡si!)
Luego cloné eso en un nuevo directorio y moví su carpeta .git a esta. p.ej
(¡Sí! ¡Finalmente limpiado!)
Después de verificar que todo está bien, puede eliminar los directorios
../large_dot_git
y../tmpdir
(tal vez en un par de semanas o un mes a partir de ahora, por si acaso ...)fuente
--prune-empty
al comando filter-branch.Reescribir el historial de Git exige cambiar todos los ID de confirmación afectados, por lo que todos los que estén trabajando en el proyecto deberán eliminar sus copias antiguas del repositorio y hacer un nuevo clon después de haber limpiado el historial. Cuantas más personas molesten, más necesitará una buena razón para hacerlo: su archivo superfluo no está causando realmente un problema, pero si solo usted está trabajando en el proyecto, que también podría limpiar el historial Git si quieres ¡a!
Para hacerlo lo más fácil posible, recomendaría usar el BFG Repo-Cleaner , una alternativa más simple y más rápida a la
git-filter-branch
diseñada específicamente para eliminar archivos del historial de Git. Una forma de facilitarle la vida aquí es que en realidad maneja todas las referencias por defecto (todas las etiquetas, ramas, etc.) pero también es 10 - 50 veces más rápido.Debe seguir cuidadosamente los pasos aquí: http://rtyley.github.com/bfg-repo-cleaner/#usage , pero el bit central es solo esto: descargue el jar BFG (requiere Java 6 o superior) y ejecute este comando :
Se analizará todo el historial del repositorio y se eliminará cualquier archivo llamado
filename.orig
(que no esté en su último commit ). ¡Esto es considerablemente más fácil que usargit-filter-branch
para hacer lo mismo!Divulgación completa: soy el autor del BFG Repo-Cleaner.
fuente
fuente
Solo para agregar eso a la solución de Charles Bailey, simplemente utilicé un git rebase -i para eliminar archivos no deseados de un commit anterior y funcionó de maravilla. Los pasos:
fuente
La forma más sencilla que encontré fue sugerida por
leontalbot
(como comentario), que es una publicación publicada por Anoopjohn . Creo que vale la pena su propio espacio como respuesta:(Lo convertí en un script bash)
Todos los créditos van a
Annopjohn
, y aleontalbot
para señalarlo.NOTA
Tenga en cuenta que el script no incluye validaciones, así que asegúrese de no cometer errores y de tener una copia de seguridad en caso de que algo salga mal. A mí me funcionó, pero puede que no funcione en tu situación. ÚSELO CON PRECAUCIÓN (siga el enlace si desea saber qué está pasando).
fuente
Definitivamente,
git filter-branch
es el camino a seguir.Lamentablemente, esto no será suficiente para eliminar por completo
filename.orig
de su repositorio, ya que todavía se puede hacer referencia a él mediante etiquetas, entradas de registro, controles remotos, etc.Recomiendo eliminar todas estas referencias también y luego llamar al recolector de basura. Puede usar el
git forget-blob
script de este sitio web para hacer todo esto en un solo paso.git forget-blob filename.orig
fuente
Si es la última confirmación que desea limpiar, probé con git versión 2.14.3 (Apple Git-98):
fuente
git reflog expire --expire=now --all; git gc --prune=now
Es algo muy malo que hacer. A menos que se esté quedando sin espacio en disco, deje que git basura recolecte estas confirmaciones después de unas semanasPara esto
git filter-branch
fue diseñado.fuente
También puedes usar:
git reset HEAD file/path
fuente