Paksa LF eol dalam git repo dan copy pekerjaan

170

Saya memiliki repositori git yang diinangi di github. Banyak file awalnya dikembangkan di Windows, dan saya tidak terlalu berhati-hati dengan akhiran baris. Ketika saya melakukan commit awal, saya juga tidak memiliki konfigurasi git untuk menegakkan akhir baris yang benar. Hasilnya adalah saya memiliki sejumlah file dengan akhiran garis CRLF di repositori github saya.

Saya sekarang mengembangkan sebagian di Linux, dan saya ingin membersihkan akhir baris. Bagaimana saya bisa memastikan file disimpan dengan benar dengan LF di github, dan memiliki LF di copy pekerjaan saya?

Saya telah menyiapkan .gitattributesfile yang berisi text eol=LF; Apakah itu benar? Dengan komitmen dan dorongan itu, bisakah saya hanya rmrepo lokal dan klon ulang dari github untuk mendapatkan efek yang diinginkan?

Chowlett
sumber
1
kemungkinan duplikat git yang menggantikan LF dengan CRLF
Lazy Badger
Tidak satu pun dari itu yang saya tanyakan. Saya satu-satunya pengembang, dan saya cukup bersedia untuk mengatur semua mesin saya sama. Saya memiliki repo yang sudah ada dengan beberapa file CRLF sudah berkomitmen untuk itu, dan beberapa klon pada mesin yang berbeda. Bagaimana saya bisa memperbarui repo, dan masing-masing copy pekerjaan, sehingga ada LF di mana-mana?
Chowlett
Sudahkah Anda melihat panduan Github ini ?
Andy

Jawaban:

237

Tanpa sedikit informasi tentang file apa yang ada di repositori Anda (kode sumber murni, gambar, file yang dapat dieksekusi, ...), agak sulit untuk menjawab pertanyaannya :)

Selain itu, saya akan mempertimbangkan bahwa Anda bersedia untuk default ke LF sebagai akhiran baris di direktori kerja Anda karena Anda bersedia memastikan bahwa file teks memiliki akhiran LF di dalam .git repositori Anda bekerja di Windows atau Linux . Memang lebih baik aman daripada menyesal ....

Namun, ada alternatif yang lebih baik: Manfaat dari ujung jalur LF di workdir Linux Anda, ujung jalur CRLF di ujung Windows workdir Anda DAN ujung jalur LF di repositori Anda.

Saat Anda sedang mengerjakan sebagian Linux dan Windows, pastikan core.eol diatur ke nativedan core.autocrlfdiatur ke true.

Kemudian, ganti konten .gitattributesfile Anda dengan yang berikut ini

* text=auto

Ini akan membuat Git menangani konversi akhir baris automagic untuk Anda, saat melakukan dan checkout. File biner tidak akan diubah, file yang terdeteksi sebagai file teks akan melihat akhiran baris dikonversi dengan cepat.

Namun, karena Anda tahu konten repositori Anda, Anda dapat membantu Git dan membantunya mendeteksi file teks dari file biner.

Asalkan Anda bekerja pada proyek pemrosesan gambar berbasis C, ganti konten .gitattributesfile Anda dengan yang berikut ini

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

Ini akan memastikan file yang ekstensi c, h, atau txt akan disimpan dengan ujung garis LF di repo Anda dan akan memiliki ujung garis asli di direktori kerja. File jpeg tidak akan disentuh. Semua yang lain akan mendapat manfaat dari penyaringan automagic yang sama seperti yang terlihat di atas.

Untuk mendapatkan pemahaman yang lebih dalam tentang detail bagian dalam dari semua ini, saya sarankan Anda untuk menyelami postingan yang sangat bagus ini "Pikirkan akhir dari garis Anda" dari Tim Clem, seorang Githubber.

Sebagai contoh dunia nyata, Anda juga dapat mengintip komit ini di mana perubahan itu menjadi a.gitattributes tersebut ditunjukkan.

Perbarui jawaban dengan mempertimbangkan komentar berikut

Saya sebenarnya tidak ingin CRLF di direktori Windows saya, karena lingkungan Linux saya sebenarnya adalah VirtualBox yang berbagi direktori Windows

Masuk akal. Terimakasih atas klarifikasinya. Dalam konteks khusus ini, the.gitattributes file itu sendiri tidak akan cukup.

Jalankan perintah berikut terhadap repositori Anda

$ git config core.eol lf
$ git config core.autocrlf input

Karena repositori Anda dibagi antara lingkungan Linux dan Windows Anda, ini akan memperbarui file konfigurasi lokal untuk kedua lingkungan. core.eolakan memastikan file teks menghasilkan ujung garis LF saat checkout. core.autocrlfakan memastikan potensi CRLF dalam file teks (dihasilkan dari operasi salin / tempel misalnya) akan dikonversi ke LF di repositori Anda.

Secara opsional, Anda dapat membantu Git membedakan apa itu file teks dengan membuat .gitattributesfile yang berisi sesuatu yang serupa dengan yang berikut:

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

Jika Anda memutuskan untuk membuat .gitattributesfile, komit saja .

Terakhir, pastikan git statusmenyebutkan "tidak ada komitmen (direktori kerja bersih)" , kemudian lakukan operasi berikut

$ git checkout-index --force --all

Ini akan membuat ulang file Anda di direktori kerja Anda, dengan mempertimbangkan perubahan konfigurasi Anda dan .gitattributes file dan mengganti potensi CRLF yang terlewatkan dalam file teks Anda.

Setelah ini selesai, setiap file teks dalam direktori kerja Anda AKAN menanggung ujung garis LF dan git statusharus tetap menganggap workdir sebagai bersih.

nulltoken
sumber
34
Saya sebenarnya tidak ingin CRLF di direktori Windows saya, karena lingkungan Linux saya sebenarnya adalah VirtualBox yang berbagi direktori Windows; dan sementara Notepad ++ dll. dapat menangani LF-only pada Windows, vikurang senang dengan CRLF. Apakah saya hanya ingin mengubahnya sehingga core.autocrlfadalah false(atau input)?
Chowlett
5
Jawaban yang sangat bagus. Catatan cepat untuk orang lain yang menggunakan pengaturan ini: Baris "* text = auto" harus menjadi baris pertama dalam file .gitattributes Anda sehingga baris selanjutnya dapat menimpa pengaturan itu.
Ari Patrick
9
@ CMCDragonkai Tergantung pada shell Anda, git checkout-index --force --allmungkin berfungsi lebih baik. Poin kedua terlihat sedikit keluar dari topik tentang pertanyaan awal. Bagaimana dengan mengajukan pertanyaan khusus?
nulltoken
8
Saya tidak mengerti mengapa .gitattributes tidak dapat menangani kasus berbagi copy pekerjaan antara Linux dan Windows. Tidak bisakah kami menetapkan textdan eol=lfmencapai hasil yang sama seperti yang dijelaskan dalam jawaban Anda melalui core.eoldan core.autocrlf?
DanielSank
10
git checkout-index --force --alltidak melakukan apa pun untuk saya. Apa yang berhasil adalah daftar perintah dalam instruksi GitHub untuk menangani masalah ini.
Roman Starkov
127

Dimulai dengan git 2.10 (dirilis 2016-09-03), tidak perlu menghitung setiap file teks secara terpisah. Git 2.10 memperbaiki perilaku text = auto bersamaan dengan eol = lf . Sumber .

.gitattributes file di root repositori git Anda:

* text=auto eol=lf

Tambahkan dan komit.

Setelah itu, Anda dapat melakukan langkah-langkah berikut dan semua file dinormalisasi sekarang:

git rm --cached -r .  # Remove every file from git's index.
git reset --hard      # Rewrite git's index to pick up all the new line endings.

Sumber: Jawaban oleh kenorb .

koppor
sumber
7
Git 2.10 telah dirilis pada 3 September 2016.
stil
Saya menjalankan ini dan menutup semua file non-teks saya
Anthony
Anda dapat secara eksplisit mengatur mode biner ke file tertentu. - Saya ingin tahu mengapa deteksi otomatis (masih ?!) rusak pada beberapa file
koppor
Ini harus menjadi jawaban yang diterima.
CletusW
25

Untuk memaksa akhir baris LF untuk semua file teks, Anda dapat membuat .gitattributesfile di tingkat atas repositori Anda dengan baris berikut (ubah sesuai keinginan):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

yang memastikan bahwa semua file yang Git anggap sebagai file teks telah menormalkan ( LF) akhiran baris dalam repositori (biasanya core.eolkonfigurasi mengontrol yang mana yang Anda miliki secara default).

Berdasarkan pengaturan atribut baru, file teks apa pun yang mengandung CRLF harus dinormalisasi oleh Git. Jika ini tidak akan terjadi secara otomatis, Anda dapat me-refresh repositori secara manual setelah mengubah akhir baris, sehingga Anda dapat memindai ulang dan melakukan direktori kerja dengan langkah-langkah berikut (diberikan direktori kerja bersih):

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

atau sesuai dokumen GitHub :

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git's index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

Lihat juga: @Charles Bailey post .

Selain itu, jika Anda ingin mengecualikan file apa pun agar tidak diperlakukan sebagai teks, batalkan atribut teksnya, mis

manual.pdf      -text

Atau tandai secara eksplisit sebagai biner:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

Untuk melihat beberapa file normalisasi git yang lebih canggih, periksa .gitattributesdi Drupal core :

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

Lihat juga:

kenorb
sumber
2
1. text=automenyesatkan. Anda tidak bisa menggunakan text=autodan eolbersama. Pengaturan eolmenonaktifkan deteksi otomatis file teks. Inilah sebabnya mengapa Anda harus menentukan semua jenis file tersebut. Jika autodiaktifkan, Anda tidak perlu semua itu. 2. Anda tidak perlu textdan eol=lf. eol=lfset secara efektif text.
Ben
2
2nd apa yang dikatakan @Ben, konfigurasi ini saat ini salah dan berbahaya jika Anda tidak secara eksplisit menandai semua file biner.
Michael R
1
Saya telah membaca bahwa * text=auto eol=lfyang pertama text=autoditimpa oleh eol=lf. Di mana Anda menemukan fitur ini? Inilah sumber saya: stackoverflow.com/questions/29435156/…
CMCDragonkai
Dihapus * text=auto eol=lfdari contoh, karena dihapus dari Drupal juga. Pertimbangkan juga untuk menghapus komentar.
kenorb
4
Penting untuk dicatat bahwa apa yang dikatakan @Ben tidak lagi benar dan selalu bug - bukan perilaku yang dimaksudkan.
Semmel