git clone git@github.com:erocarrera/pydot
( 35a8d858b ) en Debian con la git config core.autocrlf input
muestra:
modified: test/graphs/b545.dot modified: test/graphs/b993.dot modified: test/graphs/cairo.dot
Estos files tienen terminaciones de línea CRLF, por ejemplo:
$ file test/graphs/cairo.dot test/graphs/cairo.dot: UTF-8 Unicode text, with CRLF line terminators
El file .gitattributes
contiene :
*.py eol=lf *.dot eol=lf *.txt eol=lf *.md eol=lf *.yml eol=lf *.png binary *.ps binary
Cambiar core.autocrlf
no tiene ningún efecto en el estado de estos files. La eliminación de .gitattributes
tampoco tiene ningún efecto. Cambiar estos files con dos2unix
no cambia su estado (como se esperaba), y de vuelta con unix2dos
no se ve diferencia con una copy anterior. Los permissions de file no cambian con ls -lsa
. Además, los files tienen terminaciones de línea uniformes por lo que puedo decir con vi -b
(por lo tanto, no debería ser el caso de que unix2dos
o dos2unix
conviertan de terminaciones de línea mixtas a uniformes, lo que podría haber explicado este extraño comportamiento). Estoy usando git
versión 2.11.0.
¿Qué piensa git
que ha cambiado?
Algo relevante:
No encontré una respuesta que explique este comportamiento durante mi búsqueda en varias discusiones. Este problema surgió de pydot
# 163 .
Con más detalle:
git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: test/graphs/b545.dot modified: test/graphs/b993.dot modified: test/graphs/cairo.dot no changes added to commit (use "git add" and/or "git commit -a") git diff test/graphs/b993.dot warning: CRLF will be replaced by LF in test/graphs/b993.dot. The file will have its original line endings in your working directory. diff --git a/test/graphs/b993.dot b/test/graphs/b993.dot index e87e112..8aa0872 100644 --- a/test/graphs/b993.dot +++ b/test/graphs/b993.dot @@ -1,10 +1,10 @@ -diGraph G{ -graph [charset="utf8"] -1[label="Umlaut"]; -2[label="ü"]; -3[label="ä"]; -4[label="ö"]; -1->2; -1->3; -1->4; -} +diGraph G{ +graph [charset="utf8"] +1[label="Umlaut"]; +2[label="ü"]; +3[label="ä"]; +4[label="ö"]; +1->2; +1->3; +1->4; +}
ACTUALIZAR:
Por curiosidad, cometí uno de estos files, arrojé git log -1 -p > diff
y vi -b diff
muestra que git
normalizó
1 commit 2021d6adc1bc8978fa08d729b3f4d565f9b89651 2 Author: 3 Date: 4 5 DRAFT: experiment to see what changed 6 7 diff --git a/test/graphs/b545.dot b/test/graphs/b545.dot 8 index ebd3e8f..2c33f91 100644 9 --- a/test/graphs/b545.dot 10 +++ b/test/graphs/b545.dot 11 @@ -1,9 +1,9 @@ 12 -digraph g {^M 13 -^M 14 -"N11" ^M 15 - [^M 16 - shape = record^M 17 - label = "<p0>WFSt|1571 as Ref: 1338 D"^M 18 -]^M 19 -N11ne -> N11:p0^M 20 -}^M 21 +digraph g { 22 + 23 +"N11" 24 + [ 25 + shape = record 26 + label = "<p0>WFSt|1571 as Ref: 1338 D" 27 +] 28 +N11ne -> N11:p0 29 +}
Otras observaciones raras: git checkout
cualquiera de estos files después de la clonación no tiene ningún efecto. Después de la confirmación anterior, el file b545.dot
continúa teniendo terminaciones de línea CLRF en el directory de trabajo. La aplicación de dos2unix
seguido de unix2dos
no hizo que git
pensara que había cambiado (mientras que antes de la confirmación sí, probablemente porque el file comprometido tenía terminaciones de línea CLRF).
Esto sucede precisamente porque esos files están comprometidos con terminaciones CRLF, sin embargo, el file .gitattributes
dice que los comprometerá con terminaciones solo LF.
Git puede y va a hacer la conversión de solo CRLF contra LF en dos lugares:
Durante la extracción del índice al tree de trabajo. Siempre se supone que un file almacenado en una confirmación o en el índice está en un estado "limpio", pero al extraer ese file del índice, al tree de trabajo, Git debe aplicar las conversiones dirigidas por .gitattributes
en forma de "cambie LF-only to CRLF", por ejemplo, y también en la forma de lo que Git llama filters de borrones .
Durante la copy de un file del tree de trabajo volver al índice. Un file almacenado en el tree de trabajo está en estado "manchado", por lo que en este punto, Git debe aplicar conversiones de "limpieza": por ejemplo, cambie CR-LF a LF solamente y aplique filters limpios .
Tenga en count que hay dos puntos en los que pueden ocurrir estas conversiones. Esto no significa que ocurrirán en ambos puntos, solo que estos son los dos lugares posibles. Como las notas de documentation de .gitattributes
, las conversiones reales son:
eol=lf
: none en index -> work-tree; CR-LF a LF-only en work-tree -> index eol=crlf
: solo LF a CR-LF en índice -> tree de trabajo; ninguno en work-tree -> index Ahora, un file que está realmente en el repository, almacenado en una confirmación, es puramente de solo lectura. Nunca puede cambiar dentro de ese compromiso. Más precisamente, la confirmación identifica (mediante ID de hash) un tree que identifica (mediante ID de hash) un blob que tiene cualquier contenido que tenga. Estas ID de hash son en sí mismas sums de verificación criptográficas de los contenidos de los objects, por lo que son, por supuesto, de solo lectura: si tratamos de cambiar los contenidos, lo que obtenemos es un nuevo object diferente con una nueva ID de hash diferente.
Debido a que el process de git checkout
realidad funciona al hacer frente a los identificadores hash sin procesar del tree o treees de compromiso al índice, las versiones de los files almacenados en el índice son necesariamente idénticas a las almacenadas en el compromiso.
Por lo tanto, si de alguna manera, independientemente de cómo , los files comprometidos están en una forma que no .gitattributes
con lo que .gitattributes
ordera a Git, los files se volverán "sucios" en el tree de trabajo, independientemente del hecho de que no lo haya hecho cualquier cosa para ellos! Si tuviera que git add
los tres files en cuestión, los copyría del tree de trabajo al índice y, por lo tanto, eliminaría los retornos de carro de sus terminaciones de línea. Por lo tanto, están, en términos de git status
, modificados pero aún no configurados para commit.
Excluir los retornos de carro en las versiones de tree de trabajo los deja en el mismo estado: se modifican con respecto a lo que hay en el índice, porque git add
dejará sin cambios sus terminaciones de línea solo LF, produciendo files nuevos y diferentes que están en el índice.
Una pregunta más interesante es: ¿cómo entraron en la (s) comisión (es) en el estado equivocado? Esto no es algo que podamos responder: solo aquellos que hicieron esos compromisos pueden producir esa respuesta. Solo podemos especular. Una forma de lograr esto es agregar y confirmar los files sin un .gitattributes
en vigencia, luego establecer los .gitattributes
en vigencia sin git add
nuevamente los files. De esta forma, las terminaciones CR-LF entran en el índice de alguien y, por lo tanto, entran en las confirmaciones de ese usuario, aunque el file .gitattributes
ahora dice (pero no dijo antes) que cualquier nueva git add
debería quitar los retornos de carro.
Cambiar
core.autocrlf
no tiene ningún efecto en el estado de estos files
Debería, pero solo después de la clonación nuevamente:
git config --global core.autocrlf false git clone git@github.com:erocarrera/pydot pydot2 cd pydot2 git status
Eso desactivaría core.autocrlf
globalmente, pero esto es solo para probar aquí.
Gracias a @torek por la explicación (que está de acuerdo con mi conjetura ).
En resumen, la configuration de git
asimétrica lleva a commit(checkout(Index))
no es la asignación de identidad. Con CRLF en el índice, esta configuration particular comprobó CRLF, pero después de las transformaciones de input en vigor ( eol=lf
), git
confirmaría LF en lugar de CRLF.
La causa de esta confusión fue comparar:
Esto no muestra si el file ha cambiado. Lo que uno debería comparar es lo que se comprometerá git
después de aplicar las transformaciones de input con lo que ya está comprometido. Claramente, si esos dos elementos difieren, entonces el file ha cambiado.
Siguiendo este razonamiento, uno podría declarar el repository "inestable", en el sentido de que se considera modificado en ausencia de interacción con el mundo. Esto permite evitar este estado cambiando los files comprometidos a LF, o cambiando los .gitattributes
(prefiero .gitattributes
LF).
En esta situación, git
confirmaría LF para LF y CRLF en el directory de trabajo, por lo que dos2unix
y unix2dos
tendrían ningún efecto en el resultado de la confirmación, por lo tanto, tampoco en el estado del file.