Apakah mungkin bagi git-merge untuk mengabaikan perbedaan akhir baris?

150

Apakah mungkin untuk git mergemengabaikan perbedaan garis akhir?

Mungkin saya mengajukan pertanyaan yang salah ... tetapi:

Saya mencoba uisng config.crlf inputtetapi segalanya menjadi agak berantakan dan di luar kendali, khususnya ketika saya menerapkannya setelah fakta .

Untuk satu hal, menerapkan konfigurasi ini setelah fakta tampaknya tidak mempengaruhi file yang dikomit ke repositori sebelum menerapkan opsi ini. Hal lain adalah bahwa tiba-tiba semua komitmen sekarang menghasilkan banyak pesan peringatan yang mengganggu tentang CRLF yang dikonversi ke LF.

Sejujurnya, saya tidak terlalu peduli apa yang digunakan untuk mengakhiri baris, saya pribadi lebih suka gaya Unix \n, tapi apa pun itu. Yang saya pedulikan, adalah untuk git mergemenjadi sedikit lebih pintar dan mengabaikan perbedaan dalam garis akhir.

Terkadang saya memiliki dua file yang identik, tetapi git akan menandainya sebagai konflik (dan konflik adalah keseluruhan file) hanya karena mereka menggunakan karakter akhir baris yang berbeda.

Memperbarui:

Saya mengetahui bahwa git diffmenerima --ignore-space-at-eolopsi, apakah mungkin untuk git mergemenggunakan opsi ini juga?

Hasen
sumber
28
Oh saya berharap. Hal akhir baris ini di git benar-benar rusak
1800 INFORMASI
Baru saja menambahkan test case yang menggambarkan alat penggabung pihak ketiga tersebut akan mengabaikan gaya eol saat penggabungan
VonC
Jadi, untuk mengklarifikasi (dari apa yang bisa saya tentukan): tidak ada cara untuk membuat git mengabaikan CR tetapi mengeluh tentang semua spasi spasi tambahan lainnya?
Stephen
Pastikan untuk melihat jawaban di bawah ini tentanggit config merge.renormalize true
qneill

Jawaban:

115

Pembaruan 2013:

Versi git terbaru mengotorisasi penggunaan gabungan dengan opsirecursive strategi dan strategi ( ):-X

git merge -s rekursif -Xignore-space-at-eol

Tetapi menggunakan " -Xignore-space-change" juga kemungkinan

  • Fab-V menyebutkan di bawah ini :
    git gabungkan master -s rekursif -X renormalize
    
    

jakub.g juga berkomentar bahwa strategi ini juga bekerja dengan memetik ceri :

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

Ini bekerja lebih baik daripada ignore-all-space.


Jawaban asli (Mei 2009)

Tambalan untuk mengabaikan gaya eol telah diusulkan pada Juni 2007 , tetapi itu hanya menyangkut git diff --ignore-space-at-eol, bukan git merge.

Pada saat itu, pertanyaan telah diajukan:

Haruskah --ignore-space-at-eolmenjadi pilihan git-merge?
Penggabungan adalah tempat pentingnya fungsi ini.
Apa semantik dari gabungan yang diselesaikan secara otomatis dengan opsi-opsi yang berlaku - apakah mereka hanya digunakan untuk mengubah nama deteksi, atau apakah kita, misalnya, tidak menandai konflik dengan hanya perubahan spasi putih? Dan jika tidak, versi mana yang kami terima secara otomatis?

Julio C Hamano tidak terlalu antusias:

Ini tentu saja menggoda, tetapi saya curiga harus diserahkan pada putaran selanjutnya.
Saya menduga bahwa itu akan memperkenalkan konsep dua jenis diff yang berbeda, satu untuk diproses secara mekanis (yaitu digunakan dalam penggabungan dengan "git-merge-rekursif", dan menerapkan dengan "git-am"), dan yang lain untuk diperiksa oleh manusia untuk mengerti.
Seringkali mungkin berguna untuk melakukan input pada kasus yang terakhir, walaupun output dari membandingkan file input yang munged mungkin tidak mudah digunakan untuk aplikasi mekanis.

Gagasan umum, jika menyangkut git merge, adalah untuk bergantung pada alat gabungan pihak ketiga.

Sebagai contoh, saya telah mengatur DiffMerge menjadi alat untuk Git merge, menetapkan seperangkat aturan yang memungkinkan alat gabungan tersebut mengabaikan eol untuk jenis file tertentu.


Setup pada Windows, dengan MSysGit1.6.3, baik untuk sesi DOS atau Git bash, dengan DiffMerge atau KDiff3:

  • set direktori ke PATH Anda (di sini:) c:\HOMEWARE\cmd.
  • tambahkan di direktori itu script merge.sh (wrapper untuk alat gabungan favorit Anda)

merge.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Nyatakan bungkus gabungan Anda untuk Git

Perintah konfigurasi git:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • Periksa apakah autoCRLF salah

git config di tingkat sistem:

git config ---system core.autoCRLF=false
  • Uji itu, ketika dua baris identik (tetapi karakter eolnya), baik DiffMerge atau KDiff3 akan mengabaikan baris tersebut selama penggabungan.

Script DOS (catatan: perintah dos2unix berasal dari sini , dan digunakan untuk mensimulasikan gaya Unix eol-style. Perintah itu telah disalin dalam direktori yang disebutkan di awal jawaban ini.):

C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_merge>git mergetool Merging the files: a.txt Normal merge conflict for 'a.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):

Pada titik ini (Memukul "kembali"), DiffMerge atau KDiff3 akan terbuka, dan Anda akan melihat sendiri baris mana yang sebenarnya digabung, dan baris mana yang diabaikan.

Peringatan : file hasil akan selalu dalam mode Windows eol (CRLF) dengan DiffMerge ...
KDiff3 menawarkan untuk menyimpan dengan satu atau lain cara.

VONC
sumber
Terima kasih atas tipnya! Meld dan FileMerge di Mac tampaknya juga merupakan aplikasi yang hebat.
Léo Léopold Hertz 준영
1
Sebagai info, strategi juga bekerja dengan memetik ceri : git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize (ini bekerja lebih baik daripada ignore-all-space)
jakub.g
1
@ jakub.g Poin bagus! Saya telah memasukkannya dalam jawaban untuk lebih banyak visibilitas.
VonC
98

Saya mencari jawaban yang sama dan saya menemukan ini

Menggabungkan cabang dengan atribut checkin / checkout yang berbeda

Jika Anda telah menambahkan atribut ke file yang menyebabkan format repositori kanonik untuk file itu berubah, seperti menambahkan filter clean / smudge atau atribut text / eol / ident, menggabungkan apa pun di mana atribut tidak ada di tempat biasanya akan menyebabkan penggabungan konflik. .

Untuk mencegah konflik penggabungan yang tidak perlu ini, git dapat diperintahkan untuk menjalankan virtual check-out dan check-in dari ketiga tahapan file saat menyelesaikan penggabungan tiga arah dengan mengatur variabel konfigurasi merge.renormalize. Ini mencegah perubahan yang disebabkan oleh konversi check-in dari menyebabkan konflik penggabungan palsu ketika file yang dikonversi digabungkan dengan file yang belum dikonversi.

Selama "smudge → clean" menghasilkan output yang sama dengan "clean" bahkan pada file yang sudah tercoreng, strategi ini akan secara otomatis menyelesaikan semua konflik terkait filter. Filter yang tidak bertindak dengan cara ini dapat menyebabkan konflik gabungan tambahan yang harus diselesaikan secara manual.

Jadi menjalankan perintah ini di repositori apa pun akan melakukan trik:

git config merge.renormalize true
Fabio
sumber
20
Sekarang ini layak menjadi jawaban default. Banyak yang telah berubah sejak pertanyaan pertama kali diajukan, penanganan git atas hal ini sekarang dibangun dengan merge. Melakukan normalisasi seperti yang Anda katakan.
Anton I. Sipos
Ini luar biasa .. selamatkan hari saya
matthaeus
4

Apa yang saya lakukan adalah membiarkan semuanya sebagai default (mis. Autocrlf = true), sentuh semua file (temukan. -Exec touch {} \;), biarkan git melihatnya sebagai 'dimodifikasi' dan komit kembali, dan selesai dengan itu. Kalau tidak, Anda akan selalu terganggu oleh pesan yang mengganggu atau perbedaan yang mengejutkan, atau harus mematikan semua fitur ruang putih git.

Anda akan kehilangan informasi kesalahan, tetapi lebih baik melakukannya lebih cepat daripada nanti :)

Ben Hymers
sumber
4

"git merge -Xrenormalize" bekerja seperti pesona.

Jake
sumber
1

http://stahlforce.com/dev/index.php?tool=remcrlf

Saya sudah mencobanya, tetapi jika setelah baris terakhir dalam kode Anda Anda belum memiliki CRLF itu menambahkan dengan sendirinya LF dan file terlihat berubah di git. Selain itu berfungsi.

manusia Semut
sumber
0

Tampaknya bagi saya sekarang bahwa cara terbaik adalah dengan menormalkan akhir baris pada kedua cabang (dan komit) sebelum menggabungkannya.

Saya googled "convert crlf ke lf" dan menemukan ini sebagai hasil pertama:
http://stahlforce.com/dev/index.php?tool=remcrlf

Saya mengunduhnya dan digunakan, sepertinya alat yang bagus.

>sfk remcr . .py

Pastikan untuk menentukan direktori dan tipe file (misalnya .py) jika tidak, ia mungkin akan mencoba mengacaukan isi .gitdirektori!

Hasen
sumber
0

AFAICT, (saya belum mencobanya) yang bisa Anda gunakan git diffuntuk membandingkan cabang yang ingin Anda gabungkan dengan leluhur yang sama, lalu terapkan hasilnya git apply. Kedua perintah memiliki --ignore-whitespaceopsi untuk mengabaikan kesalahan akhir baris dan spasi.

Sayangnya, jika tambalan tidak berlaku bersih, seluruh operasi dibatalkan. Anda tidak dapat memperbaiki gabungan konflik. Ada --rejectopsi untuk meninggalkan bakhil yang tidak dapat ditonton dalam .rejfile, yang membantu, tetapi tidak sama dengan memiliki konflik gabungan ditampilkan dalam satu file.

rjmunro
sumber
-1

Setelah membaca Atasi konflik gabungan: Paksa menimpa semua file

Saya akhirnya menyelesaikan versi masalah ini. Saya mencoba untuk menarik pembaruan dari repo hulu tetapi yang saya miliki saat ini mengalami masalah terkait CRLF dan tidak dapat bergabung sebagai hasilnya. Perlu dicatat bahwa saya tidak memiliki PERUBAHAN LOKAL yang perlu saya khawatirkan. Langkah-langkah berikut mengatasi masalah saya:

Sesuai instruksi github tentang sinkronisasi garpu ( https://help.github.com/articles/syncing-a-fork/ ):

  1. git fetch upstream

  2. git reset --hard upstream/master
    Pemahaman git saya yang terbatas memberi tahu saya bahwa ini adalah melakukan apa yang saya inginkan - mengubah garpu saya (tanpa perubahan yang sebenarnya tidak dikomit) untuk mendapatkan semua perubahan yang dilakukan pada sumber hulu. Menurut halaman sumber, langkah ini biasanya tidak diperlukan, tetapi masalah CRLF mengharuskannya.

  3. git merge upstream/master

  4. git push
diperbanyak
sumber
1
Anda sadar bahwa git reset --hard upstream/mastermembuang cabang lokal Anda dan mengarahkannya ke upstream/master, membuat git merge upstream/masterno-op?
Christoffer Hammarström
-1

Namun saya menyarankan untuk menggunakan alat seperti sed untuk mencapai akhir baris yang benar, dan kemudian file diff. Saya menghabiskan beberapa jam di diffing proyek dengan berbagai akhir baris.

Cara terbaik adalah:

  1. salin hanya file proyek (hapus .gitdirektori) ke direktori lain buat repositori di dalamnya, kemudian tambahkan file dan komit (harus ada di cabang master di repositori baru).
  2. salin file dari proyek kedua ke folder yang sama, tetapi cabang lain misalnya dev( git checkout -b dev), komit file di cabang ini dan jalankan (jika proyek pertama adalah master): git diff master..dev --names-only untuk melihat nama file yang diubah saja
pengguna4686964
sumber