El estado de Git ignora los finales de línea / archivos idénticos / entorno windows y linux / dropbox / mled

113

Como hago

estado de git

ignorar las diferencias de final de línea?

Información de antecedentes:

Utilizo aleatoriamente Windows y Linux para trabajar en el proyecto. El proyecto está en Dropbox.

Encontré mucho sobre cómo hacer que git diff ignore los finales de línea. Como utilizo meld, git diff abre meld para cada archivo. Y meld dice "archivo idéntico".

Entonces, ¿cómo evito esto? Git solo debería abrir meld para archivos modificados. Y el estado de git no debe informar que los archivos han cambiado si solo el final del archivo es diferente.

EDITAR: Causa:

Esto sucedió debido a esta configuración en Windows

core.autocrlf true

Así que revisé la copia de trabajo en Linux y configuré core.autocrlf como falso en Windows.

Sería bueno saber cómo hacer que git status ignore diferentes líneas nuevas.

Thorsten Niehues
fuente
3
Si está compartiendo el archivo usando Dropbox en diferentes plataformas, esto ocurrirá a menos que le diga explícitamente a git que trate todos los archivos como binarios. La solución adecuada es no usar dropbox para repositorios de git
Petesh
tenga en cuenta: stackoverflow.com/questions/2825428/… - esto puede ayudar un poco
Petesh
Descubrí cómo funciona bien con Dropbox: estableciendo core.autocrlf false
Thorsten Niehues
3
AFAIK decirle a git que trate los archivos como binarios también tiene el efecto secundario de cambiar la forma en que difiere el archivo. La solución adecuada es decirle a git que ignore los finales de línea. 2 de mis cosas favoritas: tratar los problemas finales de línea y FUD snarky innecesaria sobre la forma de ajustar sus repositorios hasta :)
crisma
Vaya, me tomó un tiempo que este problema core.autocrlfsea ​​la causa raíz en Windows, pero también una cura en Linux. El problema es que autocrlfes global en Windows y el repositorio no tiene esa configuración .git/config. Al ejecutar un local, git config core.autocrlf trueme deshice de los cambios falsos en mi copia de trabajo NTFS clonada en Windows pero accedida en Linux. (ahora solo hay cambios espurios con enlaces simbólicos - los enlaces simbólicos NTFS FUNCIONAN en montajes fuseblk, pero Git los ve como modificados ...)
Tomasz Gandor

Respuestas:

104

Intente configurar el valor core.autocrlf de esta manera:

git config --global core.autocrlf true
Saša Šijak
fuente
7
@ThorstenNiehues Utilizo esa configuración en algún proyecto de trabajo. En el trabajo debo usar windows, en casa uso mac y linux. Antes de esto, tenía el mismo problema que tú, después de esa configuración todo estaba bien.
Saša Šijak
1
Eso es extraño porque un pago en Windows tiene \ r \ n finales de línea solo en Linux \ n ¿Tienes ambas copias de trabajo en Dropbox (o similar)?
Thorsten Niehues
1
@ThorstenNiehues No, el repositorio de git está en github. Hmm, ¿tal vez Dropbox de alguna manera está arruinando los finales de línea cuando sincroniza archivos? Parece extraño usar dropbox para git. Intente usar bitbucket (tiene repositorios privados gratuitos), solo haga un pequeño repositorio y pruebe en sus 2 máquinas con algunos pequeños archivos de texto.
Saša Šijak
1
1. La copia de trabajo y el repositorio local están en Dropbox (no necesito un repositorio público) esa es probablemente la diferencia
Thorsten Niehues
3
En Windows: core.autocrlf truees una configuración de trabajo en CygWin. core.safecrlf falsees un entorno de trabajo en git bash o mingw
DrumM
43

Utilice .gitattributes en su lugar, con la siguiente configuración:

# Ignore all differences in line endings
*        -crlf

.gitattributes se encontraría en el mismo directorio que su .gitconfig global. Si .gitattributes no existe, agréguelo a ese directorio. Después de agregar / cambiar .gitattributes, tendrá que hacer un restablecimiento completo del repositorio para aplicar con éxito los cambios a los archivos existentes.

Hombre basura
fuente
Me funcionó en una secuencia, pero cuando intenté crearlo en otra secuencia para el mismo proyecto, todavía muestra diferencias de Newline.
pfernandom
1
@pfernandom, ¿es posible que tenga varios .gitattributes en su proyecto? Primero verá la versión más "local", por lo que si tiene una en el directorio local donde están los archivos, la usará sobre la de todo el proyecto.
Trashman
¿Necesita tener 8 espacios antes de -crlf?
Igonato
No debería importar
Trashman
Esto hace más que simplemente ignorar los finales de línea para git status. De hecho, cambia la forma en que se registran los archivos en el repositorio. ref: git-scm.com/docs/gitattributes#_code_text_code
Vince
31

Esta respuesta parece relevante ya que el OP hace referencia a la necesidad de una solución de múltiples sistemas operativos. Este artículo de ayuda de Github detalla los enfoques disponibles para manejar los finales de las líneas entre sistemas operativos. Existen enfoques globales y por repositorio para administrar los finales de línea entre sistemas operativos.

Enfoque global

Configure el manejo de finales de línea de Git en Linux u OS X:

git config --global core.autocrlf input

Configure el manejo de finales de línea de Git en Windows:

git config --global core.autocrlf true

Enfoque por repositorio:

En la raíz de su repositorio, cree un .gitattributesarchivo y defina la configuración de final de línea para los archivos de su proyecto, una línea a la vez en el siguiente formato: path_regex line-ending-settingsdonde line-ending-settingses uno de los siguientes:

  • texto
  • binario (archivos para los que Git no debería modificar los finales de línea, ya que esto puede hacer que algunos tipos de imágenes, como PNG, no se procesen en un navegador)

El textvalor se puede configurar más para instruir a Git sobre cómo manejar los finales de línea para los archivos coincidentes:

  • text - Cambia los finales de línea a los finales de línea nativos del sistema operativo.
  • text eol=crlf- Convierte los finales de línea CRLFen al finalizar la compra.
  • text eol=lf- Convierte los finales de línea LFen al finalizar la compra.
  • text=auto - Valor predeterminado sensato que deja el control de la línea a discreción de Git.

Aquí está el contenido de un archivo .gitattributes de muestra:

# Set the default behavior for all files.
* text=auto

# Normalized and converts to 
# native line endings on checkout.
*.c text
*.h text

# Convert to CRLF line endings on checkout.
*.sln text eol=crlf

# Convert to LF line endings on checkout.
*.sh text eol=lf

# Binary files.
*.png binary
*.jpg binary

Más información sobre cómo actualizar su repositorio después de cambiar la configuración de los finales de línea aquí . Tldr:

Haga una copia de seguridad de sus archivos con Git, elimine todos los archivos de su repositorio (excepto el directorio .git) y luego restaure todos los archivos a la vez. Guarde sus archivos actuales en Git, para que no se pierda nada de su trabajo.

git add . -u

git commit -m "Saving files before refreshing line endings"

Elimina el índice y obliga a Git a volver a escanear el directorio de trabajo.

rm .git/index

Vuelva a escribir el índice de Git para recoger todos los nuevos finales de línea.

git reset

Muestra los archivos normalizados y reescritos.

En algunos casos, esto es todo lo que se necesita hacer. Otros pueden necesitar completar los siguientes pasos adicionales:

git status

Vuelva a agregar todos sus archivos modificados y prepárelos para una confirmación. Esta es su oportunidad de inspeccionar qué archivos, si los hay, no se modificaron.

git add -u

Es perfectamente seguro ver aquí muchos mensajes que dicen "advertencia: CRLF será reemplazado por LF en el archivo".

Vuelva a escribir el archivo .gitattributes.

git add .gitattributes

Confirme los cambios en su repositorio.

git commit -m "Normalize all the line endings"

usuario4603841
fuente
18

Problema relacionado con los comandos git en el sistema operativo Windows:

$ git add --all

advertencia: LF será reemplazado por CRLF en ...

El archivo tendrá sus finales de línea originales en su directorio de trabajo.

Resolución :

$ git config --global core.autocrlf false     
$ git add --all 

No aparece ningún mensaje de advertencia.

Winstonhong
fuente
debe hacer esto en todos los sistemas operativos que esté utilizando, es decir, en Windows y en Linux. Recuerde que cada sistema operativo tiene su propio archivo .git / config global, por lo que debe hacer que esos ajustes sean similares. Por eso @Thorsten tenías problemas. Pero configuré la bandera en verdadero en lugar de falso.
Emmanuel Mahuni
Esta solución también funciona en Linux (la respuesta de @ SašaŠijak no me
funcionó
4

Creé un script para ignorar las diferencias en los finales de línea:

Mostrará los archivos que no se agregaron a la lista de confirmación y se modificaron (después de ignorar las diferencias en los finales de línea). Puede agregar el argumento "agregar" para agregar esos archivos a su confirmación.

#!/usr/bin/perl

# Usage: ./gitdiff.pl [add]
#    add : add modified files to git

use warnings;
use strict;

my ($auto_add) = @ARGV;
if(!defined $auto_add) {
    $auto_add = "";
}

my @mods = `git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-`;
chomp(@mods);
for my $mod (@mods) {
    my $diff = `git diff -b $mod 2>/dev/null`;
    if($diff) {
        print $mod."\n";
        if($auto_add eq "add") {
            `git add $mod 2>/dev/null`;
        }
    }
}

Código fuente: https://github.com/lepe/scripts/blob/master/gitdiff.pl

Actualizaciones :

  • corrección por evandro777: cuando el archivo tiene espacio en el nombre de archivo o directorio
lepe
fuente
¡Gracias! Esa es la única forma en que podría obtener la diferencia real. Solo hay un problema que sucedió con 3 líneas impresas, que muestra este error: sh: 1: Error de sintaxis: Cadena entre comillas no
terminada
1
Una solución para un problema de script: El problema: cuando el archivo tiene espacio en el nombre de archivo o directorio, git usará "", por lo que el script se rompe. La solución es cambiar esta línea: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | awk '{ print \$2 }'; a esto: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-;
evandro777
@ evandro777: ¡Gracias! He actualizado tanto la respuesta como el código git.
lepe
3

Utilizo Windows y Linux, pero la solución core.autocrlf trueno me ayudó. Incluso no cambié nada después git checkout <filename>.

Así que utilizo una solución alternativa para sustituir git status:gitstatus.sh

#!/bin/bash

git status | grep modified | cut -d' ' -f 4 | while read x; do
 x1="$(git show HEAD:$x | md5sum | cut -d' ' -f 1 )"
 x2="$(cat $x | md5sum | cut -d' ' -f 1 )"

 if [ "$x1" != "$x2" ]; then
    echo "$x NOT IDENTICAL"
 fi
done

Solo comparo md5sumun archivo y su hermano en el repositorio.

Salida de ejemplo:

$ ./gitstatus.sh
application/script.php NOT IDENTICAL
application/storage/logs/laravel.log NOT IDENTICAL
shukshin.ivan
fuente
2
tal vez pueda usar "git diff -b" para cada archivo para verificar cambios excel cambios en espacios en blanco
Ivan