salir - overwrite last commit git
Tratando de arreglar los finales de lĂnea con git filter-branch, pero sin suerte (8)
Me ha mordido el problema de fin de línea de Windows / Linux con git. Parece, a través de GitHub, MSysGit y otras fuentes, que la mejor solución es tener los repositorios locales configurados para usar los finales de línea del estilo de Linux, pero establecer core.autocrlf
en true
. Desafortunadamente, no hice esto lo suficientemente temprano, así que ahora, cada vez que hago cambios, los finales de línea se ven afectados.
Pensé que había encontrado una respuesta here pero no puedo hacer que funcione para mí. Mi conocimiento de la línea de comandos de Linux es, en el mejor de los casos, limitado, por lo que ni siquiera estoy seguro de lo que hace la línea "xargs fromdos" en su script. Sigo recibiendo mensajes acerca de que no existe tal archivo o directorio, y cuando logro apuntarlo a un directorio existente, me dice que no tengo permisos.
He intentado esto con MSysGit en Windows y a través del terminal Mac OS X.
Así es como arreglé todos los finales de línea en todo el historial usando git filter-branch
. El carácter ^M
debe ingresarse usando CTRL-V
+ CTRL-M
. Utilicé dos2unix
para convertir los archivos, ya que esto omite automáticamente los archivos binarios.
$ git filter-branch --tree-filter ''grep -IUrl "^M" | xargs -I {} dos2unix "{}"''
El "| xargs fromdos" lee desde la entrada estándar (los archivos se encuentran) y lo usa como argumentos para el comando fromdos
, que convierte los finales de línea. (¿Es fromdos estándar en esos entornos? Estoy acostumbrado a dos2unix). Tenga en cuenta que puede evitar utilizar xargs (especialmente útil si tiene suficientes archivos, la lista de argumentos es demasiado larga para xargs):
find <path, tests...> -exec fromdos ''{}'' /;
o
find <path, tests...> | while read file; do fromdos $file; done
No estoy totalmente seguro de sus mensajes de error. He probado con éxito este método. ¿Qué programa está produciendo cada uno? ¿Para qué archivos / directorios no tienes permisos? Sin embargo, aquí hay un intento de adivinar cuál podría ser:
Una forma fácil de obtener un error de "archivo no encontrado" para la secuencia de comandos es mediante una ruta relativa: use una absoluta. De manera similar, podría obtener un error de permisos si no ha hecho su script ejecutable (chmod + x).
Añade comentarios y trataré de ayudarte a resolverlo.
La documentación de git para gitattributes ahora documenta otro enfoque para "arreglar" o normalizar todos los finales de línea en su proyecto. Aquí está la esencia de esto:
$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"
Si alguno de los archivos que no deberían normalizarse se muestra en el estado de git, desactive su atributo de texto antes de ejecutar git agregue -u.
manual.pdf -text
A la inversa, los archivos de texto que git no detecta pueden tener la normalización habilitada manualmente.
weirdchars.txt text
Esto aprovecha un nuevo indicador --renormalize
agregado en git v2.16.0, lanzado en enero de 2018. Para versiones anteriores de git, hay algunos pasos más:
$ echo "* text=auto" >>.gitattributes
$ rm .git/index # Remove the index to force git to
$ git reset # re-scan the working directory
$ git status # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"
La forma más fácil de solucionar esto es hacer un compromiso que corrija todos los finales de línea. Suponiendo que no tenga ningún archivo modificado, puede hacerlo de la siguiente manera.
# From the root of your repository remove everything from the index
git rm --cached -r .
# Change the autocrlf setting of the repository (you may want
# to use true on windows):
git config core.autocrlf input
# Re-add all the deleted files to the index
# (You should get lots of messages like:
# warning: CRLF will be replaced by LF in <file>.)
git diff --cached --name-only -z | xargs -0 git add
# Commit
git commit -m "Fixed crlf issue"
# If you''re doing this on a Unix/Mac OSX clone then optionally remove
# the working tree and re-check everything out with the correct line endings.
git ls-files -z | xargs -0 rm
git checkout .
Mi procedimiento para tratar con los finales de línea es el siguiente (batalla probada en muchos repositorios):
Al crear un nuevo repositorio:
- ponga
.gitattributes
en la primera confirmación junto con otros archivos típicos como.gitignore
yREADME.md
Cuando se trata de un repositorio existente:
- Crea / modifica
.gitattributes
consecuencia -
git commit -a -m "Modified gitattributes"
-
git rm --cached -r . && git reset --hard && git commit -a -m ''Normalize CRLF'' -n"
-
-n
(--no-verify
es omitir los enlaces de confirmación previa) - Tengo que hacerlo con la frecuencia suficiente para definirlo como un alias
alias fixCRLF="..."
-
- repite el comando anterior
- Sí, es vudú, pero generalmente tengo que ejecutar el comando dos veces, la primera vez normaliza algunos archivos, y la segunda vez incluso más archivos. En general, es probable que sea mejor repetir hasta que no se cree un nuevo compromiso :)
- Ir y volver entre la antigua (justo antes de la normalización) y la nueva rama varias veces. Después de cambiar la rama, ¡a veces git encontrará incluso más archivos que deben volver a normalizarse!
En .gitattributes
declaro explícitamente que todos los archivos de texto tienen LF EOL, ya que generalmente las herramientas de Windows son compatibles con LF, mientras que las herramientas que no son de Windows no son compatibles con CRLF (incluso muchas herramientas de línea de comandos de nodejs asumen LF y, por lo tanto, pueden cambiar el EOL en sus archivos) .
Contenido de .gitattributes
Mis .gitattributes
usualmente se ven como:
*.html eol=lf
*.js eol=lf
*.json eol=lf
*.less eol=lf
*.md eol=lf
*.svg eol=lf
*.xml eol=lf
Para averiguar qué extensiones distintas son rastreadas por git en el repositorio actual, mira aquí
Problemas después de la normalización
Una vez hecho esto, hay una advertencia más común sin embargo.
Digamos que su master
ya está actualizado y normalizado, y luego se retira outdated-branch
. Muy a menudo, justo después de revisar esa rama, git marca muchos archivos como modificados.
La solución es hacer un commit falso ( git add -A . && git commit -m ''fake commit''
) y luego git rebase master
. Después de la rebase, el compromiso falso debería desaparecer.
Siga estos pasos si ninguna de las otras respuestas funciona para usted:
- Si está en Windows, haga
git config --global core.autocrlf true
; Si estás en Unix, hazgit config core.autocrlf input
- Ejecutar
git rm --cached -r .
- Eliminar el archivo
.gitattributes
- Ejecutar
git add -A
- Ejecutar
git reset --hard
Entonces tu local debería estar limpio ahora.
de acuerdo ... bajo cygwin no tenemos disponibles fácilmente archivos de dosis, y awk substeb explota en su cara si tiene espacios en las rutas de acceso a los archivos modificados (que teníamos), así que tuve que hacerlo de manera algo diferente:
git status --short | grep "^ *M" | sed ''s/^ *M//'' | xargs -n 1 dos2unix
felicitaciones a @lloyd por la mayor parte de esta solución
git status --short|grep "^ *M"|awk ''{print $2}''|xargs fromdos
Explicación:
git status --short
Esto muestra cada línea que git es y no tiene en cuenta. Los archivos que no están bajo el control de git se marcan al principio de la línea con un ''?''. Los archivos que se modifican están marcados con una M.
grep "^ *M"
Esto filtra solo aquellos archivos que han sido modificados.
awk ''{print $2}''
Esto muestra solo el nombre del archivo sin ningún marcador.
xargs fromdos
Esto toma los nombres de archivo del comando anterior y los ejecuta a través de la utilidad ''fromdos'' para convertir los finales de línea.