Stan Git ignoruje zakończenia linii / identyczne pliki / środowisko Windows i Linux / dropbox / mled

113

Jak to zrobić

status git

zignorować różnice w końcówkach linii?

Podstawowe informacje:

Do pracy nad projektem używam losowo systemów Windows i Linux. Projekt znajduje się w Dropbox.

Dowiedziałem się wiele o tym, jak sprawić, by git diff ignorował zakończenia linii. Ponieważ używam meld git diff otwiera meld dla każdego pliku. A połączenie mówi „identyczny plik”.

Jak więc tego uniknąć. Git powinien otwierać połączenie tylko dla zmienionych plików. Status git nie powinien zgłaszać plików jako zmienionych, jeśli tylko ich zakończenie jest inne.

EDYCJA: Przyczyna:

Stało się tak z powodu tego ustawienia w systemie Windows

core.autocrlf prawda

Więc sprawdziłem kopię roboczą na Linuksie i ustawiłem core.autocrlf false na Windows.

Byłoby miło wiedzieć, jak sprawić, by status git ignorował różne nowe linie.

Thorsten Niehues
źródło
3
Jeśli udostępniasz plik za pomocą Dropbox na różnych platformach, tak się stanie, chyba że wyraźnie powiesz gitowi, aby traktował wszystkie pliki jako binarne. Właściwym rozwiązaniem nie jest używanie dropboxa do repozytoriów git
Petesh,
uwaga
Dowiedziałem się, jak to działa dobrze z Dropbox: ustawiając core.autocrlf false
Thorsten Niehues
3
AFAIK nakazanie gitowi traktowania plików jako binarnych ma również efekt uboczny polegający na zmianie sposobu, w jaki porównuje plik. Właściwym rozwiązaniem jest nakazanie programowi git ignorowania końcówek linii. 2 z moich najmniej ulubionych rzeczy: radzenie sobie z problemami z zakończeniem linii i niepotrzebnym
złośliwym FUDem na
Wow, zajęło mi trochę czasu, że ten problem core.autocrlfjest główną przyczyną w systemie Windows, ale także lekarstwem na Linuksie. Problem polega na tym, że autocrlfjest globalny w systemie Windows, a repozytorium nie ma tego ustawienia .git/config. Uruchamiając lokalnie git config core.autocrlf truepozbyłem się fałszywych zmian w mojej kopii roboczej NTFS sklonowanej w systemie Windows, ale uzyskano do niej dostęp w systemie Linux. (teraz są tylko fałszywe zmiany w dowiązaniach symbolicznych - dowiązania symboliczne NTFS DZIAŁAJĄ na montowaniach fuseblk, ale Git widzi je jako zmodyfikowane ...)
Tomasz Gandor

Odpowiedzi:

105

Spróbuj ustawić wartość core.autocrlf w następujący sposób:

git config --global core.autocrlf true
Saša Šijak
źródło
7
@ThorstenNiehues Używam tego ustawienia w jakimś projekcie. W pracy muszę korzystać z systemu Windows, w domu używam Maca i Linuksa. Wcześniej miałem ten sam problem co Ty, po tym ustawieniu wszystko było ok.
Saša Šijak
1
To dziwne, ponieważ kasowanie w systemie Windows ma \ r \ n zakończenia wierszy tylko w systemie Linux \ n Czy masz obie kopie robocze w Dropbox (lub podobnym)?
Thorsten Niehues
1
@ThorstenNiehues Nie, repozytorium git jest na github. Hmm, może Dropbox w jakiś sposób wkręca się z zakończeniami linii, gdy synchronizuje pliki? Używanie Dropbox dla git wydaje się dziwne. Spróbuj użyć bitbucket (ma darmowe prywatne repozytoria), po prostu stwórz jedno małe repozytorium i przetestuj na swoich 2 maszynach za pomocą małych plików tekstowych.
Saša Šijak
1
1. Kopia robocza i lokalne repozytorium znajdują się w Dropbox (nie potrzebuję repozytorium publicznego) to prawdopodobnie różnica
Thorsten Niehues
3
W systemie Windows: core.autocrlf trueto ustawienie robocze w CygWin. core.safecrlf falseto działające ustawienie w git bash lub mingw
DrumM
43

Zamiast tego użyj .gitattributes z następującym ustawieniem:

# Ignore all differences in line endings
*        -crlf

.gitattributes można znaleźć w tym samym katalogu, co globalny plik .gitconfig. Jeśli .gitattributes nie istnieje, dodaj go do tego katalogu. Po dodaniu / zmianie .gitattributes będziesz musiał wykonać twardy reset repozytorium, aby pomyślnie zastosować zmiany w istniejących plikach.

Śmieciarz
źródło
Działało dla mnie w jednym strumieniu, ale kiedy próbowałem utworzyć go w innym strumieniu dla tego samego projektu, nadal pokazuje różnice w Newline.
pfernandom
1
@pfernandom, czy prawdopodobnie masz w swoim projekcie wiele atrybutów .gitat? Najpierw sprawdzi najbardziej „lokalną” wersję, więc jeśli masz taką w katalogu lokalnym, w którym znajdują się pliki, użyje jej w całym projekcie.
Trashman
Czy musi mieć 8 spacji przed -crlf?
Igonato,
To nie powinno mieć znaczenia
Trashman
To robi więcej niż tylko ignorowanie końcówek linii dla git status. W rzeczywistości zmienia sposób wpisywania plików do repozytorium. ref: git-scm.com/docs/gitattributes#_code_text_code
Vince
31

Ta odpowiedź wydaje się istotna, ponieważ PO odwołuje się do potrzeby rozwiązania obejmującego wiele systemów operacyjnych. Ten artykuł pomocy Github zawiera szczegółowe informacje na temat dostępnych metod obsługi zakończeń linii w różnych systemach operacyjnych. Istnieją podejścia globalne i per-repo do zarządzania zakończeniami linii między systemami operacyjnymi.

Globalne podejście

Skonfiguruj obsługę końcówek linii Git w systemie Linux lub OS X:

git config --global core.autocrlf input

Skonfiguruj obsługę końcówek linii Git w systemie Windows:

git config --global core.autocrlf true

Podejście per-repo:

W katalogu głównym repozytorium utwórz .gitattributesplik i zdefiniuj ustawienia zakończenia linii dla plików projektu, po jednej linii na raz w następującym formacie: path_regex line-ending-settingsgdzie line-ending-settingsjest jednym z następujących:

  • tekst
  • binarne (pliki, dla których Git nie powinien modyfikować końcówek linii - ponieważ może to spowodować, że niektóre typy obrazów, takie jak PNG, nie będą renderowane w przeglądarce)

textWartość może być dodatkowo skonfigurowany pouczać Git na jak radzić końca linii dla plików pasujące:

  • text - Zmienia zakończenia linii na natywne zakończenia linii systemu operacyjnego.
  • text eol=crlf- Konwertuje zakończenia linii na CRLFprzy kasie.
  • text eol=lf- Konwertuje zakończenia linii na LFprzy kasie.
  • text=auto - Rozsądne ustawienie domyślne, które pozostawia obsługę linii w gestii Gita.

Oto zawartość przykładowego pliku .gitattributes:

# 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

Więcej o tym, jak odświeżyć repozytorium po zmianie ustawień zakończeń linii tutaj . Tldr:

wykonaj kopię zapasową plików za pomocą Gita, usuń każdy plik w repozytorium (z wyjątkiem katalogu .git), a następnie przywróć wszystkie pliki naraz. Zapisz swoje bieżące pliki w Git, aby nic nie zostało utracone.

git add . -u

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

Usuń indeks i wymuś ponowne przeskanowanie katalogu roboczego przez Git.

rm .git/index

Przepisz indeks Git, aby zebrać wszystkie nowe zakończenia linii.

git reset

Pokaż przepisane, znormalizowane pliki.

W niektórych przypadkach to wszystko, co należy zrobić. Inni mogą potrzebować wykonać następujące dodatkowe kroki:

git status

Dodaj z powrotem wszystkie zmienione pliki i przygotuj je do zatwierdzenia. To Twoja szansa, aby sprawdzić, które pliki, jeśli w ogóle, pozostały niezmienione.

git add -u

Jest całkowicie bezpieczne, aby zobaczyć tutaj wiele wiadomości, które brzmią [s] "ostrzeżenie: CRLF zostanie zastąpiony przez LF w pliku."

Przepisz plik .gitattributes.

git add .gitattributes

Zatwierdź zmiany w swoim repozytorium.

git commit -m "Normalize all the line endings"

user4603841
źródło
18

Problem związany z poleceniami git w systemie operacyjnym Windows:

$ git add --all

ostrzeżenie: LF zostanie zastąpiony przez CRLF w ...

Plik będzie miał oryginalne zakończenia linii w katalogu roboczym.

Rozdzielczość :

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

Nie pojawiają się żadne komunikaty ostrzegawcze.

winstonhong
źródło
powinieneś to zrobić we wszystkich systemach operacyjnych, których używasz, tj .: w systemie Windows i Linux. Pamiętaj, że każdy system operacyjny ma swój własny globalny plik .git / config, więc musisz uczynić te ustawienia identycznymi. Dlatego @Thorsten miałeś problemy. Ale ustawiłem flagę na true zamiast false.
Emmanuel Mahuni
To rozwiązanie działa również w Linuksie (odpowiedź @ SašaŠijak nie działa dla mnie)
juliocesar
4

Stworzyłem skrypt, aby ignorować różnice w zakończeniach linii:

Wyświetli pliki, które nie zostały dodane do listy zatwierdzeń i zostały zmodyfikowane (po zignorowaniu różnic w zakończeniach linii). Możesz dodać argument „add”, aby dodać te pliki do swojego zatwierdzenia.

#!/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`;
        }
    }
}

Kod źródłowy: https://github.com/lepe/scripts/blob/master/gitdiff.pl

Aktualizacje :

  • naprawiono przez evandro777: gdy plik ma miejsce w nazwie pliku lub katalogu
lepe
źródło
Dzięki! Tylko w ten sposób mogłem uzyskać prawdziwą różnicę. Wystąpił tylko problem, który wystąpił z wydrukowanymi 3 wierszami, pokazując ten błąd: sh: 1: Błąd składniowy: niezakończony cytowany ciąg
evandro777
1
Poprawka dotycząca problemu ze skryptem: Problem: gdy plik ma miejsce w katalogu nazwa_pliku ou, git użyje „”, więc skrypt się zepsuje. Rozwiązaniem jest zmiana tej linii: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | awk '{ print \$2 }'; do tego: my @mods = git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-;
evandro777,
@ evandro777: Dzięki! Zaktualizowałem zarówno odpowiedź, jak i kod git.
lepe
3

Używam zarówno Windowsa, jak i Linuksa, ale rozwiązanie core.autocrlf truemi nie pomogło. Po tym nawet nic się nie zmieniło git checkout <filename>.

Więc używam obejścia, aby zastąpić 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

Po prostu porównuję md5sumplik i jego brat w repozytorium.

Przykładowe dane wyjściowe:

$ ./gitstatus.sh
application/script.php NOT IDENTICAL
application/storage/logs/laravel.log NOT IDENTICAL
shukshin.ivan
źródło
2
być może możesz użyć "git diff -b" dla każdego pliku, aby sprawdzić zmiany Excela zmiany białych znaków
Ivan