Jak zmusić git do używania LF zamiast CR + LF pod Windows?

335

Chcę zmusić gita do pobierania plików w systemie Windows, używając po prostu LFnie CR+LF. Sprawdziłem dwie opcje konfiguracji, ale nie byłem w stanie znaleźć odpowiedniej kombinacji ustawień.

Chcę, aby przekonwertować wszystkie pliki LFi zachować je LFw plikach.

Uwaga: Użyłem, autocrlf = inputale to tylko naprawia pliki, gdy je zatwierdzasz. Chcę go zmusić, aby ich używał LF.

Prawdopodobnie nie byłem tak jasny: repozytorium już używa, LFale pliki wyewidencjonowane za pomocą msysgit używają CR+LFi chcę zmusić msysgit do uzyskania LF: wymuszania zakończenia linii uniksowych .

>git config --list | grep crlf
core.autocrlf=input
sorin
źródło
2
autocrlf=inputjest prawidłową opcją. Oczywiście nie chroni cię przed plikami, które naprawdę mają cr+lfw repozytorium lub tworzeniem plików za pomocą cr+lfinnego narzędzia przed dodaniem ich do git. Jakie masz problemy, że to nie działa?
CB Bailey,
2
Pliki w repozytorium używają już tylko, LFale kiedy otrzymam je w systemie Windows, msysgit konwertuje je na CR+LF.
sorin,
Coś musi być z twoją konfiguracją; Właśnie przetestowałem to na mojej instalacji msysgit. Przy autocrlfustawieniu na inputgit pozostawia lfźródła linii w spokoju. Czy możesz opublikować wynik git config?
CB Bailey,
1
W takim przypadku sugeruję zarejestrowanie błędu; najlepiej wskazując na repozytorium testowe, które wykazuje problem, i podaj kroki do odtworzenia, ponieważ zachowanie, które widzisz, jest zdecydowanie niewłaściwe (ale nie mogę go odtworzyć).
CB Bailey
1
Mała wskazówka to także upewnić się, że uruchamiasz polecenia git na „git”, o którym myślisz, że tak. Na przykład możesz mieć git zainstalowany na Windowsie i git zainstalowany na cygwin, więc upewnij się, że ustawiłeś właściwą konfigurację git.
Fred

Odpowiedzi:

106

OP dodał w swoim pytaniu:

Pliki wyewidencjonowane za pomocą msysgit są używane CR+LFi chcę zmusić msysgit do ich pobraniaLF

Pierwszym prostym krokiem nadal byłby .gitattributesplik:

# 2010
*.txt -crlf

# 2020
*.txt text eol=lf 

(jak wspomniano w komentarzach przez wnuka , odnosząc się do .gitattributesEnd-of-line konwersji ), aby uniknąć CRLFkonwersję plików z poprawna eol.

I zawsze zalecałem git config --global core.autocrlf false wyłączenie jakiejkolwiek konwersji (która miałaby zastosowanie do wszystkich wersjonowanych plików)

Zobacz najlepsze praktyki dotyczące wieloplatformowej konfiguracji git?

Od wersji 2.16 Git (Q1 2018) możesz git add --renormalize .natychmiast zastosować te .gitattributesustawienia.


Ale drugi, bardziej zaawansowany krok obejmuje sterownik filtra gitattribute i dodaje krok rozmazywania

sterownik filtra

Ilekroć aktualizujesz działające drzewo, skrypt może, tylko dla plików określonych w .gitattributes, wymusić LF eoli każdą inną opcję formatowania, którą chcesz wymusić.
Jeśli clearskrypt „ ” nic nie robi, będziesz (po zatwierdzeniu) transformował pliki, stosując dokładnie taki format, jakiego potrzebujesz.

VonC
źródło
Jedno pytanie: * .txt dotyczy wszystkich plików z rozszerzeniem .txt lub wszystkich plików tekstowych (niebinarnych)? Nie mogę utworzyć listy z wszelkiego rodzaju rozszerzeniami plików, które będę mieć w projekcie.
sorin
1
@Sorin: wszystkie pliki z .txtrozszerzeniem. Lepiej najpierw to ustalić i przetestować na określonej grupie, zanim uogólnisz na *, i dodaj regułę ujemną, !*.xyz ...aby wykluczyć kilka plików z tej reguły.
VonC
1
Do tej pory .gitattributeswiersze powinny brzmieć: *.txt text eol=lfzgodnie z git-scm.com/docs/gitattributes
wnuk
@grandchild Dziękuję. W odpowiedzi umieściłem twój komentarz dla większej widoczności.
VonC
Myślę, że po dodaniu .gitattributesmusimy zrobićgit add --renormalize .
shuva
461

Właściwym sposobem na uzyskanie końcówek LF w systemie Windows jest najpierw ustawienie core.autocrlfna false:

git config --global core.autocrlf false

Musisz to zrobić, jeśli używasz msysgit, ponieważ ustawia go truew ustawieniach systemowych.

Teraz git nie dokona żadnej normalizacji kończącej linię. Jeśli chcesz sprawdzić w pliki mają być znormalizowane, to zrobić: Ustaw text=autow swojej .gitattributesdla wszystkich plików:

* text=auto

I ustaw core.eolna lf:

git config --global core.eol lf

Teraz możesz także przełączyć pojedyncze repozytorium na crlf (w katalogu roboczym!), Uruchamiając

git config core.eol crlf

Po zakończeniu konfiguracji możesz chcieć, aby git znormalizował wszystkie pliki w repozytorium . Aby to zrobić, przejdź do katalogu głównego repozytorium i uruchom następujące polecenia:

git rm --cached -rf .
git diff --cached --name-only -z | xargs -n 50 -0 git add -f

Jeśli teraz chcesz, aby git również normalizował pliki w katalogu roboczym , uruchom następujące polecenia:

git ls-files -z | xargs -0 rm
git checkout .
Chronial
źródło
3
Dostaję fatalny pathspec '' nie pasuje do żadnych plików, zaraz po tymgit diff --cached --name-only -z | xargs -0 git add
CMCDragonkai
3
Jaka jest wydajność git diff --cached --name-only?
Chronial
1
Warto wspomnieć, że możesz ustawić tę konfigurację podczas klonowania danego repozytorium, np git clone --config core.autocrlf=false <repo path>.
Chris Long
240

Często wracam do tej odpowiedzi, choć żadna z nich nie jest dla mnie odpowiednia. To powiedziawszy, właściwa odpowiedź jest dla mnie mieszanką innych.

Uważam, że działa to:

 git config --global core.eol lf
 git config --global core.autocrlf input

W przypadku repozytoriów, które zostały wyrejestrowane po ustawieniu globalnych ustawień, wszystko zostanie wyrejestrowane tak, jak jest w repo - miejmy nadzieję LF( \n). Wszelkie CRLFzostaną przekonwertowane na tylko LFprzy zameldowaniu.

Przy istniejącym repozytorium, które już wypisałeś - który ma poprawne zakończenia linii w repozytorium, ale nie kopię roboczą - możesz uruchomić następujące polecenia, aby to naprawić:

git rm -rf --cached .
git reset --hard HEAD

Spowoduje to usunięcie rmrekursywnie ( r) bez pytania ( -f), wszystkie pliki oprócz tych, które edytowałeś ( --cached), z bieżącego katalogu ( .). resetNastępnie powrót wszystkich tych plików do stanu, w którym mają one swoje prawdziwe zakończeń linii (odpowiadający co jest w repo).

Jeśli chcesz naprawić zakończenia linii plików w repozytorium, zalecam skorzystanie z edytora, który pozwoli ci to zrobić zbiorczo, takiego jak IntelliJ lub Sublime Text, ale jestem pewien, że każdy dobry może to obsługiwać.

Ben Liyanage
źródło
1
Mamy jedno repozytorium z podkatalogami, które wymagają innej obsługi zakończenia linii. Tak więc ustawienie opcji globalnej nie działa w tym przypadku. Nawet w jednym repozytorium. Jak zastosować te same ustawienia w .gitattributes?
RobG
Notepad++w prawym dolnym rogu pokazuje także koniec linii otwartego pliku. Kliknięcie prawym przyciskiem myszy tego pola pozwoli Ci zmienić zakończenia linii.
winklerrr
1
core.autocrlf inputOpcja nadpisuje core.eolustawienie, więc ustawienie obu jest zbędny. (Zobacz git-scm.com/docs/git-config )
Andrew Marshall
1
Dziękuję, z twoją pomocą podbiłem linty i Linuksa. I może teraz rejestrować pliki.
GC_
57

Kontekst

Jeśli ty

  1. chcę zmusić wszystkich użytkowników do zakończenia linii LF dla plików tekstowych i
  2. nie możesz zagwarantować, że wszyscy użytkownicy zmienią konfigurację git,

możesz to zrobić zaczynając od git 2.10. Wymagane jest 2.10 lub nowsze, ponieważ 2.10 naprawiło zachowanie text = auto wraz z eol = lf . Źródło .

Rozwiązanie

Umieść .gitattributesplik w katalogu głównym repozytorium git o następującej zawartości:

* text=auto eol=lf

Zaangażuj się.

Opcjonalne poprawki

Możesz także dodać .editorconfigw katalogu głównym repozytorium, aby nowoczesne narzędzia tworzyły nowe pliki z pożądanymi zakończeniami linii.

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
koppor
źródło
3
To było dla mnie najlepsze rozwiązanie. Połączyłem to również z editorconfig.org , aby podczas pisania w Intellij napisałem LF EOL.
Jazzepi
To zdecydowanie najlepsze rozwiązanie. Nie trzeba ręcznie uruchamiać żadnych poleceń konfiguracyjnych!
Cameron Tacklind
26

core.autocrlf=inputjest właściwym ustawieniem dla tego, czego chcesz, ale może być konieczne wykonanie a git update-index --refreshi / lub a, git reset --hardaby zmiana zaczęła obowiązywać.

Po core.autocrlfustawieniu na inputgit nie będzie stosował konwersji nowego wiersza przy kasie (więc jeśli masz LF w repozytorium, dostaniesz LF), ale upewni się, że w przypadku zepsucia się i wprowadzenia niektórych CRLF w działającym jakoś skopiować, nie dostaną się do repozytorium.

kusma
źródło
19
Polecenia powinny mieć postać git rm --cached -r. && git reset --hard
koppor
0

Rozwiązanie tego problemu można znaleźć na stronie : https://help.github.com/en/github/using-git/configuring-git-to-handle-line-endings

Uproszczony opis sposobu rozwiązania tego problemu w systemie Windows:

Globalne ustawienia zakończeń linii Polecenie git config core.autocrlf służy do zmiany sposobu, w jaki Git obsługuje zakończenia linii. To wymaga jednego argumentu.

W systemie Windows po prostu przekazujesz wartość true konfiguracji. Na przykład: C:> git config --global core.autocrlf true

Powodzenia, mam nadzieję, że pomogłem.

c-santana
źródło