Qual è la migliore strategia di gestione CRLF (ritorno a capo, avanzamento riga) con Git?

Ho provato a eseguire il commit di file con righe finali CRLF, ma non è riuscito.

Ho trascorso un’intera giornata di lavoro sul mio computer Windows provando diverse strategie ed ero quasi attratto dal tentativo di usare Git e provare Mercurial .

Si prega di condividere solo una buona pratica per risposta.

Quasi quattro anni dopo aver fatto questa domanda, ho finalmente trovato una risposta che mi soddisfa completamente !

Vedi i dettagli in github: guida per la guida a Gestire le terminazioni di linea .

Git ti consente di impostare le proprietà di fine riga per un repository direttamente usando l’ attributo text nel file .gitattributes . Questo file è impegnato nel repository e sovrascrive l’impostazione core.autocrlf , consentendo di garantire un comportamento coerente per tutti gli utenti, indipendentemente dalle loro impostazioni git.

E quindi

Il vantaggio di questo è che la configurazione di fine linea viaggia ora con il tuo repository e non devi preoccuparti se i collaboratori hanno o meno le corrette impostazioni globali.

Ecco un esempio di un file .gitattributes

 # Auto detect text files and perform LF normalization * text=auto *.cs text diff=csharp *.java text diff=java *.html text diff=html *.css text *.js text *.sql text *.csproj text merge=union *.sln text merge=union eol=crlf *.docx diff=astextplain *.DOCX diff=astextplain # absolute paths are ok, as are globs /**/postinst* text eol=lf # paths that don't start with / are treated relative to the .gitattributes folder relative/path/*.txt text eol=lf 

C’è una comoda raccolta di file .gitattributes pronti all’uso per i linguaggi di programmazione più popolari. È utile per iniziare.

Dopo aver creato o regolato i tuoi .gitattributes , dovresti eseguire una normalizzazione della fine di una volta per tutte.

Si noti che l’app GitHub Desktop può suggerire e creare un file .gitattributes dopo aver aperto il repository Git del progetto nell’app. Per provarlo, fai clic sull’icona a forma di ingranaggio (nell’angolo in alto a destra)> Impostazioni repository …> Terminazioni e attributi di linea. Ti verrà chiesto di aggiungere gli .gitattributes consigliati e, se sei d’accordo, l’app eseguirà anche la normalizzazione di tutti i file nel tuo repository.

Infine, l’articolo Mind the End of Your Line fornisce ulteriori informazioni e spiega come Git si è evoluto in materia. Considero questo necessario leggere .

Probabilmente hai utenti nel tuo team che usano EGit o JGit (strumenti come Eclipse e TeamCity li usano) per impegnare le loro modifiche. Allora sei sfortunato, come ha spiegato @gatinueta nei commenti di questa risposta:

Questa impostazione non ti soddisfa completamente se nella tua squadra ci sono persone che lavorano con Egit o JGit, dal momento che tali strumenti ignorano semplicemente .gitattributes e controllano felicemente i file CRLF https://bugs.eclipse.org/bugs/show_bug.cgi? id = 342.372

Un trucco potrebbe essere quello di farli impegnare le loro modifiche in un altro client, ad esempio SourceTree . Il nostro team ha quindi preferito questo strumento a EGit di Eclipse per molti casi d’uso.

Chi ha detto che il software è facile? : – /

Non convertire le terminazioni di linea. Non è compito del VCS interpretare i dati: basta archiviarli e riprodurli. Ogni editor di testo moderno può comunque leggere entrambi i tipi di terminazioni di linea.

Quasi sempre vuoi l’ autocrlf=input meno che tu non sappia davvero cosa stai facendo.

Qualche ulteriore contesto qui sotto:

Dovrebbe essere core.autocrlf=true se ti piace DOS ending o core.autocrlf=input se preferisci unix-newlines. In entrambi i casi, il tuo repository Git avrà solo LF, che è la cosa giusta. L’unico argomento per core.autocrlf=false era che l’euristica automatica potrebbe erroneamente rilevare alcuni binari come testo e quindi la tua tessera sarà corrotta. Quindi, core.safecrlf opzione core.safecrlf stata introdotta per avvisare un utente se si verifica un cambiamento irreversibile. In effetti, ci sono due possibilità di cambiamenti irreversibili – la fine linea mista nel file di testo, in questa normalizzazione è auspicabile, quindi questo avviso può essere ignorato, o (molto improbabile) che Git abbia rilevato erroneamente il file binario come testo. Quindi devi usare gli attributi per dire a Git che questo file è binario.

Il paragrafo precedente era originariamente preso da un thread su gmane.org, ma da allora è andato giù.

Due strategie alternative per ottenere coerenza con le terminazioni di riga in ambienti misti (Microsoft + Linux + Mac):

A. Impostazione globale per tutti i repository

1) Converti tutto in un unico formato

 find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion' 

2) Impostare core.autocrlf per l’ input su Linux / UNIX o true su MS Windowns (repository o globale)

 git config --global core.autocrlf input 

3) [Facoltativo] imposta core.safecrlf su true (interrompi) o warn (su sing) per aggiungere guard extra confrontando se la trasformazione di nuova riga invertita risulterebbe nello stesso file

 git config --global core.safecrlf true 

B. O per l’installazione del repository

1) Converti tutto in un unico formato

 find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion' 

2) aggiungi il file .gitattributes al tuo repository

 echo "* text=auto" > .gitattributes git add .gitattributes git commit -m 'adding .gitattributes for unified line-ending' 

Non preoccuparti dei tuoi file binari – Git dovrebbe essere abbastanza intelligente su di loro.


Ulteriori informazioni sulle variabili safecrlf / autocrlf

Prova a impostare l’opzione di configurazione core.autocrlf su true . core.safecrlf all’opzione core.safecrlf .

In realtà suona come core.safecrlf potrebbe già essere impostato nel repository, perché (enfatizza il mio):

Se questo non è il caso per l’impostazione corrente di core.autocrlf, git rifiuterà il file .

In tal caso, è ansible verificare che l’editor di testo sia configurato per utilizzare le terminazioni di riga in modo coerente. È probabile che si verifichino problemi se un file di testo contiene una combinazione di terminazioni di linea LF e CRLF.

Infine, ritengo che la raccomandazione di “usare semplicemente ciò che viene dato” e utilizzare le righe terminate da LF su Windows causerà più problemi di quanti ne risolva. Git ha le opzioni sopra elencate per provare a gestire le terminazioni di linea in modo sensato, quindi ha senso usarle.

L’utilizzo di core.autocrlf=false impedito l’aggiornamento di tutti i file non appena li ho controllati nel mio progetto Visual Studio 2010 . Gli altri due membri del team di sviluppo utilizzano anche i sistemi Windows, quindi un ambiente misto non è entrato in gioco, tuttavia le impostazioni predefinite fornite con il repository hanno sempre contrassegnato tutti i file come aggiornati immediatamente dopo la clonazione.

Immagino che la linea di fondo sia trovare quale impostazione CRLF funzioni per il proprio ambiente. Soprattutto perché in molti altri repository sulle nostre scatole Linux l’impostazione di autocrlf = true produce risultati migliori.

20+ anni più tardi e stiamo ancora affrontando le disparità di fine linea tra sistemi operativi … triste.

Queste sono le due opzioni per gli utenti di Windows e Visual Studio che condividono il codice con utenti Mac o Linux . Per una spiegazione estesa, leggi il manuale di gitattributes .

* text = auto

Nel file .gitattributes del .gitattributes aggiungere:

 * text=auto 

Ciò normalizzerà tutti i file con terminazioni di linea LF nel repository.

A seconda del sistema operativo (impostazione core.eol ), i file nell’albero di lavoro verranno normalizzati in LF per sistemi basati su Unix o CRLF per sistemi Windows.

Questa è la configurazione utilizzata dai repository di Microsoft .NET .

Esempio:

 Hello\r\nWorld 

Sarà normalizzato nel repository sempre come:

 Hello\nWorld 

Al checkout, l’albero di lavoro in Windows sarà convertito in:

 Hello\r\nWorld 

Al checkout, l’albero di lavoro in Mac sarà lasciato come:

 Hello\nWorld 

Nota: se il repository contiene già file non normalizzati, lo git status mostrerà questi file come completamente modificati la prossima volta che apportate modifiche su di essi, e potrebbe essere un problema per gli altri utenti unire le loro modifiche in seguito. Vedere l’ aggiornamento di un repository dopo aver cambiato la fine della linea per ulteriori informazioni.

core.autocrlf = true

Se il text non è specificato nel file .gitattributes , Git utilizza la variabile di configurazione core.autocrlf per determinare se il file deve essere convertito.

Per gli utenti Windows, git config --global core.autocrlf true è una big opzione perché:

  • I file vengono normalizzati alle terminazioni di linea LF solo quando aggiunti al repository. Se ci sono file non normalizzati nel repository, questa impostazione non li toccherà.
  • Tutti i file di testo vengono convertiti in terminazioni di riga CRLF nella directory di lavoro.

Il problema con questo approccio è che:

  • Se sei un utente di Windows con l’ autocrlf = input , vedrai un mucchio di file con terminazioni di linea LF . Non è un azzardo per il resto della squadra, perché i tuoi commit saranno comunque normalizzati con finali di linea LF .
  • Se sei un utente di Windows con core.autocrlf = false , vedrai un mucchio di file con terminazioni di linea LF e potresti inserire nel repository file con terminazioni di riga CRLF .
  • La maggior parte degli utenti Mac usa autocrlf = input e potrebbe ottenere file con terminazioni di file CRLF , probabilmente da utenti Windows con core.autocrlf = false .

Questa è solo una soluzione alternativa :

In casi normali, utilizzare le soluzioni fornite con git. Questi funzionano alla grande nella maggior parte dei casi. Forza a LF se condividi lo sviluppo su sistemi basati su Windows e Unix impostando .gitattributes .

Nel mio caso c’erano> 10 programmatori che sviluppavano un progetto in Windows. Questo progetto è stato archiviato con CRLF e non c’era alcuna opzione da forzare a LF.

Alcune impostazioni sono state scritte internamente sulla mia macchina senza alcuna influenza sul formato LF; quindi alcuni file sono stati globalmente modificati in LF su ogni piccola modifica di file.

La mia soluzione:

Macchine Windows: lascia tutto com’è. Non preoccuparti di nulla, dal momento che sei uno sviluppatore di Windows ‘lone lupo’ predefinito e devi gestire in questo modo: “Non c’è nessun altro sistema nel vasto mondo, vero?”

Unix-Macchine

  1. Aggiungi le seguenti linee alla sezione [alias] di una configurazione. Questo comando elenca tutti i file modificati (cioè modificati / nuovi):

     lc = "!f() { git status --porcelain \ | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \ | cut -c 4- ; }; f " 
  2. Converti tutti i file modificati in formato DOS:

     unix2dos $(git lc) 
  3. Opzionalmente …

    1. Crea un hook git per questa azione per automatizzare questo processo

    2. Utilizzare i parametri e includerlo e modificare la funzione grep in modo che corrisponda solo a nomi di file particolari, ad esempio:

       ... | egrep -r "^(\?| ).*\.(txt|conf)" | ... 
    3. Sentiti libero di renderlo ancora più conveniente usando una scorciatoia aggiuntiva:

       c2dos = "!f() { unix2dos $(git lc) ; }; f " 

      … e licenziare le cose convertite digitando

       git c2dos 

Ho passato ore a trovare il miglior uso ansible di .gitattributes , per rendermi finalmente conto, che non posso contare su di esso.
Sfortunatamente, finché esistono editor basati su JGit (che non possono gestire correttamente .gitattributes ), la soluzione sicura è forzare LF ovunque, anche a livello di editor.

Utilizzare i seguenti disinfettanti anti-CRLF .

— Aggiornare —

Anche se non vuoi usare la strategia di cui sopra, il seguente comando è tuo amico ( Nota: su windows clients funziona solo con git-bash e sui client Linux solo se compilato usando --with-libpcre in ./configure ).

 # Print all files that have been committed with CRLF (more correctly that contain CR), so that you normalize them. git grep -I --files-with-matches --perl-regexp '\r' HEAD 

Un esempio doloroso :

netbeans 8.2 (su Windows), impegnerà erroneamente tutti i file di testo con CRLF sul repository , a meno che non abbia impostato in modo esplicito core.autocrlf come globale . Questo contraddice il comportamento del client git standard e causa molti problemi in seguito, durante l’aggiornamento / fusione. Questo è ciò che rende alcuni file appaiono diversi (anche se non lo sono) anche quando si ripristina .
Lo stesso comportamento in netbeans accade anche se hai aggiunto corretti .gitattributes al tuo progetto.

L’utilizzo del comando precedente dopo un commit, ti aiuterà almeno a rilevare in anticipo se il repository git ha problemi di fine riga.