2014-10-24 10 views
20

Git mi sta mostrando un intero file è cambiato, quando non riesco a capire le modifiche. Questo è git Cygwin, ma succede anche in msysgitGit che mostra file identici come modificati

$ git --version 
git version 2.1.1 

$ diff <(git show HEAD:File.cs) <(cat File.cs) 
// Shows no differences 

$ diff <(git show HEAD:File.cs | xxd) <(xxd File.cs) 
// Shows no differences 

$ git diff 
// shows the entire file has changed 

$ git hash-object <(git show HEAD:File.cs) 
7b3762473342a5b040835bfef9f6b45c109ba48b 

$ git hash-object <(cat File.cs) 
7b3762473342a5b040835bfef9f6b45c109ba48b 

$ git hash-object File.cs 
7b3762473342a5b040835bfef9f6b45c109ba48b 

ho

$ git config --get core.fileMode 
false 

e

$ git config --get core.autocrlf 
true 

Io veramente ho idea di cosa sta succedendo, cosa vuole che siano la lo stesso, ma git vuole creare un commit dicendo che l'intero contenuto è stato cancellato e ricreato. Qualcuno che conosce l'idraulica migliore ha un suggerimento? Tutto ciò a cui riesco a pensare è che Git Show sta rimuovendo/normalizzando le lineline dispari.

UPDATE:

sono abbastanza sicuro che suo accadere perché il processo di sviluppo è così. Checkout da git, rsync a dev machine, sviluppo, rsync back. Credo che rsync stia scherzando con le terminazioni di linea. È strano che i git non riportino i finali di linea, e sembra essere davvero confuso su cosa diavolo sta succedendo. Anche se differire la rappresentazione binaria dei file sembra essere identico.

UPDATE 2:

Quindi questo è super fastidioso, e mi sento come ho inciampato su un bug in git.

Per esempio

$ git gc 
$ git checkout -- . 
$ git clean -fd 
$ git status 

> shows a heap of modified files 

Sono abbastanza sicuro che dovrebbe mostrare nessun cambiamento, non importa dove la sua corsa, ma ho una lista delle 20 cose strane :(

+0

Vedete lo stesso con 'git config --get core.autocrlf false'? – VonC

+0

Sì, la stessa cosa. Mi sono persino assicurato di ripubblicare tutto con 'git rm --cached. -r' e 'git reset --hard'. Poi l'ho eseguito attraverso gli strumenti di sviluppo, andare a 'git status' e ottenere che l'intero file sia" cambiato ". Sono disposto ad accettare che il mio processo stia cambiando i file (immagino i finali di linea), ma voglio davvero che mi dica come. Mi sta confondendo a non finire, specialmente considerando che l'output dell'oggetto hash è lo stesso. –

+0

Quale sistema operativo e quale versione git stai usando? – VonC

risposta

17

Ciò può essere causato da un file .gitattributes che indica a git che dovrebbe fare EOL normalizzazione, ma il repository contenente fine riga non normalizzati.

la soluzione semplice è quello di rimuovere la relativa riga da .gitattributes. Questo potrebbe essere

012.
* text=auto 

o

*.cs text 

Un rapido esempio di come questo possa accadere è questa:

$ echo "Hello World" > example.txt 
$ unix2dos example.txt #Make sure it uses CRLF 
$ git add example.txt 
$ git commit -m "commit 1" 
$ #Instruct git that all .txt files should be normalized 
$ echo '*.txt text' >> .gitattributes 
$ git add .gitattributes 
$ git commit -m "commit 2" 

Ora il repository è in uno stato strano, perché .gitattributes sostiene il file deve essere normalizzata prima di aggiungerlo all'indice, ma la versione corrente impegnata non è normalizzata.

Tuttavia, a questo punto, git status non si accorge che, in quanto il file stesso non è cambiato in termini di dimensioni o di mtime da quando è stato aggiunto all'indice, così l'indice è considerato fino ad oggi:

$ git status 
On branch master 
nothing to commit, working directory clean 

Ma tutto ciò che invalida l'indice causerà git di prendere in considerazione il file per essere sporco:

$ touch example.txt 
On branch master 
Changes not staged for commit: 

     modified: example.txt 

no changes added to commit (use "git add" and/or "git commit -a") 

e git reset --hard o qualsiasi altra azione per cercare di ripristinare il file allo stato che si suppone di essere in non lo farà Aggiustalo. Questo perché non c'è modo di aggiungere il file all'indice nel suo stato attuale così come è nel repository, perché a git è stato ordinato di normalizzare quel file e che la normalizzazione non può mai produrre l'oggetto mentre è attualmente impegnato.

Questo è il motivo per pagina GITATTRIBUTES(1) uomo raccomanda di invalidare in modo esplicito l'intero indice quando si introduce la normalizzazione di fine riga in questo modo:

$ 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" 

leggere la sezione su "End-of-line conversione" nell'uomo gitattributes pagina per maggiori dettagli.

Invece di andare con la soluzione rapida di rimuovere solo quella linea da .gitattributes, si consiglia di mantenere invece la linea che termina le regole di normalizzazione e andare avanti e normalizzarle ora. In pratica, ciò significa semplicemente commettere i 20+ cambiamenti che non scompariranno, ma è possibile farlo in modo metodico seguendo le istruzioni sopra riportate sull'introduzione della normalizzazione della fine della riga (meno la modifica dello .gitattributes) e quindi sentendo che non si ripeterà più , poiché tutti i file sono ora impegnati con terminazioni normalizzate e anche eventuali file futuri aggiunti verranno normalizzati. È una preferenza personale, per lo più.