Tidak ada baris baru di akhir file

472

Ketika melakukan git diffitu dikatakan "Tidak ada baris baru di akhir file" .

Oke, tidak ada baris baru di akhir file. Apa masalahnya?

Apa pentingnya pesan itu dan apa yang ingin disampaikannya kepada kami?

Pacerier
sumber
11
Mungkin, jika Anda memiliki file yang berakhir tanpa baris baru, dan Anda menambahkan baris lain, git harus menunjukkan bahwa baris terakhir sebelumnya telah berubah, karena itu termasuk karakter baris baru sebagai bagian dari baris?
nafg

Jawaban:

458

Ini menunjukkan bahwa Anda tidak memiliki baris baru (biasanya '\n', alias CR atau CRLF) di akhir file.

Artinya, cukup berbicara, byte terakhir (atau byte jika Anda menggunakan Windows) dalam file tersebut bukan baris baru.

Pesan ditampilkan karena jika tidak, tidak ada cara untuk mengetahui perbedaan antara file di mana ada baris baru di akhir dan di mana tidak. Diff harus mengeluarkan baris baru, atau hasilnya akan lebih sulit untuk dibaca atau diproses secara otomatis.

Perhatikan bahwa ini adalah gaya yang baik untuk selalu menempatkan baris baru sebagai karakter terakhir jika diizinkan oleh format file. Lebih jauh, misalnya, untuk file header C dan C ++ diperlukan oleh standar bahasa.

Alexander Gladysh
sumber
136
Karena penasaran, dapatkah Anda menjelaskan mengapa itu dianggap gaya yang baik untuk selalu menempatkan baris baru sebagai karakter terakhir? Sunting: temukan diskusi ini .
Paul Bellora
84
@PaulBellora Secara historis, itu adalah keputusan yang dibuat oleh standar bahasa C stackoverflow.com/a/729725/233098 Praktis, karena banyak alat Unix membutuhkan atau mengharapkannya untuk tampilan yang tepat stackoverflow.com/a/729795/233098 . Secara filosofis, karena setiap baris dalam file teks berakhir dengan karakter "end-of-line" - baris terakhir tidak boleh menjadi pengecualian. Berpikir secara berbeda, mari kita jelajahi inversnya. Jika ada penanda "start-of-line" alih-alih "end-of-line", apakah Anda akan menghilangkan karakter "start-of-line" di baris pertama?
Joe
29
@ Jo. Itu tidak masuk akal. Baris baru adalah baris baru , yaitu pemisah antara garis, bukan garis akhir. Kami tidak memiliki karakter awal, karena tidak diperlukan. Kami tidak memiliki karakter garis akhir untuk alasan yang sama.
acjay
6
@acjay saya berpendapat bahwa secara inheren lebih baik antara "Pemisah antara garis" vs "end-of-line". Tidak ada pandangan yang secara inheren benar atau salah, hanya satu cara untuk melihatnya. Saya menyarankan kita terus menggunakan point-of-pandangan yang secara historis praktis, karena kita sudah melakukannya dengan cara itu dan itu tidak masuk akal ketika Anda menerimanya. Konsistensi penting. Tidak perlu mematahkan sudut pandang atas nama "pemisah antara garis".
Joe
17
@WORMSS "Baru bagi saya" tidak sama dengan "konvensi baru." Ini seperti menemukan konvensi pemrograman lainnya. Kamu hanya pergi dengan itu. Anda bisa menyimpang, tetapi Anda hanya mengisolasi diri sendiri. (Atau dalam kasus ini, benar-benar alat yang melanggar.) Pikirkan tentang berapa banyak orang lain yang menemukan beberapa konvensi Rails, atau PEP8, dan seberapa konsisten komunitas-komunitas itu tetap secara keseluruhan karena mereka menyerah - walaupun memiliki kode tertulis yang bertentangan.
Joe
100

Ini bukan hanya gaya yang buruk, itu dapat menyebabkan perilaku yang tidak terduga saat menggunakan alat lain pada file.

Ini adalah test.txt:

first line
second line

Tidak ada karakter baris baru di baris terakhir. Mari kita lihat berapa banyak baris dalam file:

$ wc -l test.txt
1 test.txt

Mungkin itu yang Anda inginkan, tetapi dalam kebanyakan kasus Anda mungkin berharap ada 2 baris dalam file.

Juga, jika Anda ingin menggabungkan file, mungkin tidak berlaku seperti yang Anda harapkan:

$ cat test.txt test.txt
first line
second linefirst line
second line

Akhirnya, itu akan membuat diff Anda sedikit lebih berisik jika Anda menambahkan baris baru. Jika Anda menambahkan baris ketiga, itu akan menampilkan suntingan ke baris kedua serta tambahan baru.

Dekan
sumber
4
Hasil dari cat ok tetapi parameter wc "-l, --lines" salah. Bahkan itu manual mengatakan "cetak jumlah baris baru" dan bukan "cetak jumlah baris".
luar biasa
Dan saya bahkan tidak dapat mereproduksi ini (wc dan cat) dengan util linux terbaru (util-linux 2.34).
wget
1
@wget saya menggunakan util-linux 2.34 dan ini bisa mengkonfirmasi bahwa apa yang dijelaskan oleh jawaban ini adalah perilaku saat ini. Dugaan saya adalah bahwa editor Anda menambahkan karakter "\ n".
stephanos
29

Satu-satunya alasan adalah bahwa Unix secara historis memiliki konvensi dari semua file teks yang dapat dibaca manusia yang diakhiri dengan baris baru. Pada saat itu, ini menghindari pemrosesan ekstra ketika menampilkan atau menggabungkan file teks, dan menghindari memperlakukan file teks secara berbeda untuk file yang berisi jenis data lain (misalnya data biner mentah yang tidak dapat dibaca manusia).

Karena konvensi ini, banyak alat dari era itu mengharapkan baris akhir, termasuk editor teks, alat diffing, dan alat pemrosesan teks lainnya. Mac OS X dibangun di atas BSD Unix, dan Linux dikembangkan agar kompatibel dengan Unix, sehingga kedua sistem operasi ini mewarisi konvensi, perilaku, dan alat yang sama.

Windows tidak dikembangkan untuk menjadi Unix-kompatibel, sehingga tidak memiliki konvensi yang sama, dan sebagian besar perangkat lunak Windows akan berurusan dengan baik tanpa baris baru.

Tetapi, sejak Git dikembangkan untuk Linux terlebih dahulu, dan banyak perangkat lunak open-source dibangun di atas sistem yang kompatibel dengan Unix seperti Linux, Mac OS X, FreeBSD, dll, sebagian besar komunitas open-source dan alat-alat mereka (termasuk bahasa pemrograman) terus berlanjut untuk mengikuti konvensi ini.

Ada alasan teknis yang masuk akal pada tahun 1971, tetapi di era ini kebanyakan konvensi dan mempertahankan kompatibilitas dengan alat yang ada.

Nathan Craike
sumber
23

Jika Anda menambahkan baris teks baru di akhir file yang sudah ada yang belum memiliki newline characterdi akhir, diff akan menunjukkan baris terakhir yang lama telah dimodifikasi, meskipun secara konseptual tidak.

Ini setidaknya satu alasan bagus untuk menambahkan newline characterdi akhir.

Contoh

File berisi:

A() {
    // do something
}

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

Anda sekarang mengeditnya

A() {
    // do something
}
// Useful comment

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

Dif git akan menampilkan:

-}
\ No newline at end of file
+}
+// Useful comment.

Dengan kata lain, ini menunjukkan perbedaan yang lebih besar daripada yang terjadi secara konseptual. Ini menunjukkan bahwa Anda menghapus baris }dan menambahkan baris }\n. Ini sebenarnya adalah apa yang terjadi, tetapi bukan itu yang terjadi secara konseptual , sehingga dapat membingungkan.

Jaseem
sumber
2
Kita dapat menulis hal yang sama di arah lain: Jika Anda menghapus baris baru di akhir file yang sudah ada yang memiliki baris baru di akhir, diff akan menunjukkan baris terakhir yang lama juga sebagai yang dimodifikasi, ketika secara konsep tidak. Setidaknya satu alasan bagus untuk menghapus baris baru di bagian akhir.
gentiane
3
@gratis Anda membingungkan "baris baru" (baris baru) dan "baris baru" (1 atau 2 karakter membatasi akhir baris)
minexew
@minexew Tidak, tuan tidak. Mungkin Anda tidak menyadari bahwa "baris baru" sama dengan "baris baru".
luar biasa
3
@TheincredibleJan Cara mereka digunakan dalam jawaban, kedua istilah memiliki arti yang berbeda. Saya tidak tahu apakah Anda mencoba menjadi orang yang sok pintar atau hanya salah paham tentang apa yang terjadi.
minexew
18

Itu hanya menunjukkan bahwa akhir file tidak memiliki baris baru. Ini bukan malapetaka, itu hanya pesan untuk membuatnya lebih jelas bahwa tidak ada satu ketika melihat perbedaan dalam baris perintah.

JohnD
sumber
10

Alasan konvensi ini dipraktikkan adalah karena pada sistem operasi mirip UNIX karakter baris baru diperlakukan sebagai terminator garis dan / atau batas pesan (ini termasuk pemipaan antara proses, penyangga garis, dll.).

Pertimbangkan, misalnya, bahwa file dengan karakter baris baru diperlakukan sebagai satu baris kosong. Sebaliknya, file dengan panjang nol byte sebenarnya adalah file kosong dengan garis nol. Ini dapat dikonfirmasi sesuai denganwc -l perintah.

Secara keseluruhan, perilaku ini masuk akal karena tidak akan ada cara lain untuk membedakan antara file teks kosong versus file teks dengan satu baris kosong jika \nkarakternya hanya pemisah baris daripada pemisah garis. Dengan demikian, file teks yang valid harus selalu diakhiri dengan karakter baris baru. Satu-satunya pengecualian adalah jika file teks dimaksudkan untuk kosong (tanpa baris).

Leslie Krause
sumber
1
Mengapa saya diturunkan -2? Saya menunjukkan tidak hanya konfirmasi dari apa jawaban lain telah menyatakan (yaitu alat berbasis standar UNIX mengharapkan baris baru sebagai terminator untuk baris) tetapi juga bahwa tidak ada cara untuk membedakan file kosong dari satu baris kosong, yang benar-benar benar . Saya secara khusus menjawab pertanyaan awal, "Apa arti penting pesan ini dan apa yang ingin disampaikannya kepada kami?"
Leslie Krause
Saya tidak downvote Anda tetapi tanggapan ini tampaknya khusus untuk sistem tipe Unix dalam hal itu hanya berlaku ketika baris baru hanya karakter baris baru. Tidak jelas apakah itu berlaku di sini. Juga, peringatan itu tampaknya tidak berguna jika file hanya terdiri dari baris kosong. Namun saya menghindari Stackoverflow karena orang sering downvote tanpa penjelasan.
user34660
9

Ada satu hal yang tidak saya lihat dalam tanggapan sebelumnya. Peringatan tentang tidak ada end-of-line bisa menjadi peringatan ketika sebagian file telah terpotong. Ini bisa menjadi gejala hilangnya data.

pengguna34660
sumber
Poin yang bagus secara umum, tapi saya pikir itu tidak masuk akal dalam konteks pertanyaan khusus ini.
cst1992
@ cst1992 Jawaban di Stackoverflow seharusnya berguna semaksimal mungkin, yang berarti mereka seharusnya berlaku untuk semua kemungkinan. Pertanyaannya singkat dan saya tidak melihat di mana itu mengecualikan kemungkinan yang saya sarankan.
user34660
7

Masalah inti adalah apa yang Anda tentukan baris dan apakah urutan karakter end-on-line adalah bagian dari baris atau tidak. Editor berbasis UNIX (seperti VIM) atau alat (seperti Git) menggunakan urutan karakter EOL sebagai terminator garis, oleh karena itu bagian dari baris. Ini mirip dengan penggunaan titik koma (;) di C dan Pascal. Dalam C titik koma mengakhiri pernyataan, dalam Pascal itu memisahkan mereka.

mmcorrelo
sumber
4

Ini sebenarnya menyebabkan masalah karena ujung baris secara otomatis memodifikasi file yang kotor tanpa membuat perubahan. Lihat posting ini untuk resolusi.

git mengganti LF dengan CRLF

Brian Blum
sumber
3

File sumber sering digabungkan dengan alat (C, C ++: file header, Javascript: bundlers). Jika Anda menghilangkan karakter baris baru, Anda bisa memperkenalkan bug jahat (di mana baris terakhir dari satu sumber disatukan dengan baris pertama dari file sumber berikutnya). Mudah-mudahan semua alat kode sumber concat di luar sana menyisipkan baris baru di antara file-file bersatu tetapi itu tidak selalu terjadi.

Inti masalahnya adalah - di sebagian besar bahasa, baris baru memiliki makna semantik dan file akhir bukanlah alternatif yang ditentukan bahasa untuk karakter baris baru. Jadi, Anda harus mengakhiri setiap pernyataan / ekspresi dengan karakter baris baru - termasuk yang terakhir.

Doug Coburn
sumber
1
Dalam C / C ++ Anda dapat menulis seluruh proyek Anda dalam satu baris. Tidak perlu baris baru.
luar biasa
Anda dapat menulis seluruh proyek Anda dalam satu baris ... jika Anda tidak menggunakan //komentar gaya di tengah kode.
Doug Coburn
2

File asli Anda mungkin tidak memiliki karakter baris baru.

Namun, beberapa editor menyukai gedit di linux diam-diam menambahkan baris baru di akhir file. Anda tidak dapat menyingkirkan pesan ini saat menggunakan editor semacam ini.

Apa yang saya coba atasi masalah ini adalah membuka file dengan editor kode studio visual

Editor ini dengan jelas menunjukkan baris terakhir dan Anda dapat menghapus baris sesuai keinginan.

Berkay92
sumber
0

Untuk apa nilainya, saya menemukan ini ketika saya membuat proyek IntelliJ pada Mac, dan kemudian memindahkan proyek ke mesin Windows saya. Saya harus membuka setiap file secara manual dan mengubah pengaturan penyandian di bagian kanan bawah jendela IntelliJ. Mungkin tidak terjadi pada kebanyakan orang jika ada yang membaca pertanyaan ini tetapi itu bisa menyelamatkan saya beberapa jam kerja ...

Lou Morda
sumber