Buat git secara otomatis menghapus spasi spasi sebelum melakukan


220

Saya menggunakan git dengan tim saya dan ingin menghapus perubahan spasi putih dari diff, log, merge, dll. Saya berasumsi bahwa cara termudah untuk melakukannya adalah dengan git secara otomatis menghapus trailing spasi putih (dan kesalahan spasi putih lainnya ) dari semua komitmen saat diterapkan.

Saya telah mencoba menambahkan berikut ini dengan ~/.gitconfigfile tetapi tidak melakukan apa-apa ketika saya komit. Mungkin ini dirancang untuk sesuatu yang berbeda. Apa solusinya?

[core]
    whitespace = trailing-space,space-before-tab
[apply]
    whitespace = fix

Saya menggunakan ruby ​​kalau-kalau ada yang punya ide spesifik ruby. Pemformatan kode otomatis sebelum melakukan akan menjadi langkah berikutnya, tapi itu masalah yang sulit dan tidak benar-benar menyebabkan masalah besar.


Jika arahan core.whitespace tidak memperbaiki masalah Anda, Anda juga dapat mengubah kait pra-komit (.git / kait / pra-komit) untuk menemukan dan memperbaikinya untuk Anda. Lihat posting ini untuk penjelasan rinci.
VolkA

2
Saya merasa frustrasi dengan kesalahan spasi putih yang serupa dan solusi parsial, dan menulis utilitas yang fleksibel dan cukup fitur lengkap yang dapat memperbaiki atau hanya melaporkan kesalahan spasi putih yang membingungkan sistem kontrol versi: Whitespace Total Fixer on Github (permintaan maaf jika ini terlalu promosi sendiri)
Dan Lenski

Jawaban:


111

Pengaturan tersebut ( core.whitespacedan apply.whitespace) tidak ada di sana untuk menghapus trailing spasi tetapi untuk:

  • core.whitespace: deteksi mereka, dan tampilkan kesalahan
  • apply.whitespace: dan menghapusnya, tetapi hanya selama patch, tidak "selalu secara otomatis"

Saya percaya git hook pre-commitakan melakukan pekerjaan yang lebih baik untuk itu (termasuk menghapus spasi spasi tambahan)


Perhatikan bahwa pada waktu tertentu Anda dapat memilih untuk tidak menjalankan pre-commithook:

  • untuk sementara: git commit --no-verify .
  • secara permanen: cd .git/hooks/ ; chmod -x pre-commit

Peringatan: secara default, pre-commitskrip (seperti ini ), belum fitur "hapus trailing", tetapi fitur "peringatan" seperti:

if (/\s$/) {
    bad_line("trailing whitespace", $_);
}

Namun Anda bisa membangun yang lebih baikpre-commit pengait yang, terutama ketika Anda mempertimbangkan bahwa:

Berkomitmen di Git dengan hanya beberapa perubahan yang ditambahkan ke area pementasan masih menghasilkan revisi "atom" yang mungkin tidak pernah ada sebagai copy pekerjaan dan mungkin tidak berfungsi .


Misalnya, orang tua mengusulkan jawaban lain, sebuah pre-commitkait yang mendeteksi dan menghapus spasi putih.
Karena kait itu mendapatkan nama file dari setiap file, saya akan merekomendasikan untuk berhati-hati untuk jenis file tertentu: Anda tidak ingin menghapus trailing spasi putih dalam .mdfile (penurunan harga)!


1
Ternyata git dapat diyakinkan untuk memperbaiki spasi putih di copy pekerjaan Anda melalui apply.whitespace, dengan menipu git agar memperlakukan perubahan copy pekerjaan Anda sebagai tambalan. Lihat jawaban saya di bawah ini .
ntc2

> "Anda tidak ingin menghapus trailing whitespace dalam file .md (markdown)" - Mengapa begitu? Apa tujuan membuntuti spasi putih dalam file penurunan harga? Saya perhatikan beberapa .editorconfigfile memiliki aturan khusus untuk itu.
friederbluemle

5
@friederbluemle tergantung pada jenis penurunan harga, spasi ganda menunjukkan <br>: github.com/FriendsOfPHP/PHP-CS-Fixer/issues/…
VonC

Pengaturan core.whitespacedengan trailing-spacedengan git configtidak meningkatkan kesalahan saat melakukan di git2.5.0.
Karl Richter

43

Anda dapat menipu Git agar memperbaiki ruang kosong untuk Anda, dengan menipu Git agar memperlakukan perubahan Anda sebagai tambalan. Berbeda dengan solusi "pre-commit hook", solusi ini menambahkan perintah memperbaiki spasi putih ke Git.

Ya, ini adalah retasan.


Solusi yang kuat

Alias ​​Git berikut diambil dari saya~/.gitconfig .

Dengan "robust", maksud saya, alias ini berjalan tanpa kesalahan, melakukan hal yang benar, terlepas dari apakah pohon atau indeksnya kotor. Namun, mereka tidak berfungsi jika interaktif git rebase -isudah berlangsung; lihat saya~/.gitconfig untuk pemeriksaan tambahan jika Anda peduli dengan kasing ini, di managit add -e trik yang dijelaskan di bagian akhir harus berfungsi.

Jika Anda ingin menjalankannya langsung di shell, tanpa membuat alias Git, cukup salin dan tempel semua yang ada di antara tanda kutip ganda (dengan asumsi shell Anda mirip Bash).

Perbaiki indeks tetapi bukan pohonnya

fixwsAlias ​​Git berikut memperbaiki semua kesalahan spasi putih dalam indeks, jika ada, tetapi tidak menyentuh hierarki:

# Logic:
#
# The 'git stash save' fails if the tree is clean (instead of
# creating an empty stash :P). So, we only 'stash' and 'pop' if
# the tree is dirty.
#
# The 'git rebase --whitespace=fix HEAD~' throws away the commit
# if it's empty, and adding '--keep-empty' prevents the whitespace
# from being fixed. So, we first check that the index is dirty.
#
# Also:
# - '(! git diff-index --quiet --cached HEAD)' is true (zero) if
#   the index is dirty
# - '(! git diff-files --quiet .)' is true if the tree is dirty
#
# The 'rebase --whitespace=fix' trick is from here:
# https://stackoverflow.com/a/19156679/470844
fixws = !"\
  if (! git diff-files --quiet .) && \
     (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git stash save FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~ && \
    git stash pop && \
    git reset --soft HEAD~ ; \
  elif (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git rebase --whitespace=fix HEAD~ && \
    git reset --soft HEAD~ ; \
  fi"

Idenya adalah untuk menjalankan git fixwssebelumnya git commitjika Anda memiliki kesalahan spasi putih dalam indeks.

Perbaiki indeks dan pohonnya

fixws-global-tree-and-indexAlias ​​Git berikut memperbaiki semua kesalahan spasi putih dalam indeks dan struktur pohon, jika ada:

# The different cases are:
# - dirty tree and dirty index
# - dirty tree and clean index
# - clean tree and dirty index
#
# We have to consider separate cases because the 'git rebase
# --whitespace=fix' is not compatible with empty commits (adding
# '--keep-empty' makes Git not fix the whitespace :P).
fixws-global-tree-and-index = !"\
  if (! git diff-files --quiet .) && \
     (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git add -u :/ && \
    git commit -m FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~2 && \
    git reset HEAD~ && \
    git reset --soft HEAD~ ; \
  elif (! git diff-files --quiet .) ; then \
    git add -u :/ && \
    git commit -m FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~ && \
    git reset HEAD~ ; \
  elif (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git rebase --whitespace=fix HEAD~ && \
    git reset --soft HEAD~ ; \
  fi"

Untuk juga memperbaiki spasi putih di file tidak berversi, lakukan

git add --intent-to-add <unversioned files> && git fixws-global-tree-and-index

Solusi sederhana tetapi tidak kuat

Versi ini lebih mudah untuk menyalin dan menempel, tetapi mereka tidak melakukan hal yang benar jika kondisi sisi mereka tidak terpenuhi.

Perbaiki sub-pohon yang di-root pada direktori saat ini (tetapi atur ulang indeks jika tidak kosong)

Menggunakan git add -euntuk "mengedit" tambalan dengan editor identitas ::

(export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .) && git checkout . && git reset

Perbaiki dan pertahankan indeks (tetapi gagal jika pohon kotor atau indeks kosong)

git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset --soft HEAD~

Perbaiki pohon dan indeks (tetapi reset indeks jika tidak kosong)

git add -u :/ && git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset HEAD~

Penjelasan export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .triknya

Sebelum saya belajar git rebase --whitespace=fixtrik dari jawaban ini saya menggunakan git addtrik yang lebih rumit di mana-mana.

Jika kami melakukannya secara manual:

  1. Setel apply.whitespaceke fix(Anda hanya perlu melakukan ini satu kali):

    git config apply.whitespace fix
    

    Ini memberitahu Git untuk memperbaiki spasi putih di patch .

  2. Meyakinkan Git untuk memperlakukan perubahan Anda sebagai tambalan :

    git add -up .
    

    Tekan a+ enteruntuk memilih semua perubahan untuk setiap file. Anda akan mendapatkan peringatan tentang Git memperbaiki kesalahan spasi putih Anda.
    ( git -c color.ui=auto diffpada titik ini mengungkapkan bahwa perubahan non-indeks Anda persis kesalahan spasi putih).

  3. Hapus kesalahan spasi putih dari copy pekerjaan Anda:

    git checkout .
    
  4. Bawa kembali perubahan Anda (jika Anda belum siap untuk melakukannya):

    git reset
    

The GIT_EDITOR=:sarana untuk menggunakan :sebagai editor, dan sebagai perintah :adalah identitas.


1
Saya baru saja mengujinya di Windows: ini berfungsi dengan baik dalam prompt perintah DOS: set VISUAL= && git add -ue . && git checkout .Perhatikan ' .' digunakan dengan git add: itu karena git1.8.3
VonC

@VonC Tidakkah hal itu menghapus VISUAL secara permanen, yang dapat menyebabkan penggunaan selanjutnya git commituntuk menggunakan editor yang salah? Saya membungkus VISUAL=bagian dalam subkulit dalam versi unix saya di atas untuk menghindari ini, tapi saya tidak tahu apakah DOS memiliki subkulit.
ntc2

1
Terima kasih untuk hack yang hebat! FYI, jika Anda telah core.editormenetapkan maka mengekspor VISUALtidak berpengaruh karena pengaturan konfigurasi diutamakan per man git-var. Untuk menimpanya, Anda harus mengekspor GIT_EDITOR=:.
Nick Felt

1
Juga, saya mengubah versi saya fixwsuntuk gagal dengan cepat jika Anda sudah dalam rebase interaktif karena jika tidak maka akan mati di git rebase --whitespace=fixgaris dan membuat Anda dalam keadaan aneh. Saya meminjam dari pertanyaan ini dan baru saja menambahkan kasus tambahan sebelum if: fixws = !"\ if test -d $(git rev-parse --git-dir)/rebase-merge ; then \ echo 'In rebase - cannot fixws' ; \ elif (! git diff-files --quiet .) && \ (! git diff-index --quiet --cached HEAD) ; then \ ...
Nick Felt

1
fyi: Saya mengadaptasikan ini ke dalam kait pre-commit
Ian Kelling

29

Saya menemukan hook pre-commit git yang menghilangkan spasi spasi .

#!/bin/sh

if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
   against=HEAD
else
   # Initial commit: diff against an empty tree object
   against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq` ; do
   # Fix them!
   sed -i 's/[[:space:]]*$//' "$FILE"
   git add "$FILE"
done
exit

3
sedDoa kedua ( sed -r 's/:[0-9]+:.*//') dapat diganti dengan cut -f1 -d:. Ini harus bekerja sama pada platform berbasis Linux dan BSD.
Ihor Kaharlichenko

2
@IhorKaharlichenko: sebenarnya, menggunakan cuttidak seaman yang kedua sed: cut akan gagal dalam (sangat tidak mungkin) kasus nama file yang mengandung ":". Anda bisa menggunakan awk 'NF>2{NF-=2}1'untuk aman
MestreLion

1
BTW, Jika Anda menggunakan Windows (msysgit) dan menggunakan core.autocrlf=true, Anda mungkin ingin menambahkan dos2unix -D "$FILE"di dalam for loop, setelah sed. Jika tidak, itu akan mengubah semua CRLF menjadi LF dengan mengeluarkan hanya sed.
jakub.g

49
Melakukan git adddi dalam kait komit sepertinya cukup jahat bagi saya. Bagaimana jika Anda melakukan pementasan / pengabdian sebagian file? Anda tidak ingin file lengkap dilakukan di belakang Anda, bukan?
Stefaan

19

Pada Mac OS (atau, kemungkinan, BSD apa saja), parameter perintah sed harus sedikit berbeda. Coba ini:

#!/bin/sh

if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
   against=HEAD
else
   # Initial commit: diff against an empty tree object
   against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -E 's/:[0-9]+:.*//' | uniq` ; do
    # Fix them!
    sed -i '' -E 's/[[:space:]]*$//' "$FILE"
    git add "$FILE"
done

Simpan file ini sebagai .git/hooks/pre-commit- atau cari yang sudah ada di sana, dan rekatkan bagian bawah di suatu tempat di dalamnya. Dan ingat juga untuk chmod a+xitu.

Atau untuk penggunaan global (melalui kait komit Git - pengaturan global ) Anda dapat memasukkannya $GIT_PREFIX/git-core/templates/hooks( di mana GIT_PREFIX adalah / usr atau / usr / lokal atau / usr / bagikan atau / opt / lokal / bagikan) dan jalankan git initdi dalam repo yang ada.

Menurut git help init:

Menjalankan git init di repositori yang ada aman. Itu tidak akan menimpa hal-hal yang sudah ada. Alasan utama untuk rerunning git init adalah untuk mengambil templat yang baru ditambahkan.


7
Bukankah kait ini memodifikasi file kerja dan menimpa indeks dengan file kerja yang dimodifikasi? Jika Anda ingin 'git add -p' untuk membuat indeks Anda, hook komit ini akan menghilangkannya.
Matthew Dutton

2
Ya, Anda mungkin benar. Seseorang mungkin harus menulis ulang skrip ini untuk menggunakan git hash-object -wdan git update-indexuntuk (kembali) memasukkan file munged langsung ke dalam indeks. Seseorang yang sangat berani.
AlexChaffee

11

Saya lebih suka menyerahkan tugas ini kepada editor favorit Anda.

Cukup atur perintah untuk menghapus spasi tambahan saat menyimpan.


2
Dalam vim Anda dapat melakukan ini dengan: autocmd BufWritePre .cpp, .c, *. H:% / \ s \ + $ // e
Robert Massaioli

3
Maaf, saya membenarkan komentar di atas sebelum mengujinya. Ada "s" yang hilang setelah tanda persen, dan itu akan memindahkan kursor di sekitar jika spasi putih ditemukan, dan itu akan menghapus pola pencarian terakhir. Lihat vim.wikia.com/wiki/Remove_unwanted_spaces untuk alternatif yang lebih baik.
Seth Johnson

1
Dalam emacs itu Mx delete-trailing-whitespace.
Mauvis Ledford

2
Lebih baik lagi, untuk emacs, atur hook untuk menghapus trailingpace sebelum menyimpan dengan menambahkan (add-hook 'before-save-hook 'delete-trailing-whitespace)ke .emacsfile Anda . Trik ruang putih Emacs
Duncan Parkes

1
Saya menggunakan (add-hook 'before-save-hook' whitespace-cleanup) yang juga mengubah tab menjadi spasi.
Nils Fagerburg

10

Menggunakan atribut git, dan menyaring pengaturan dengan konfigurasi git

OK, ini adalah taktik baru untuk menyelesaikan masalah ini ... Pendekatan saya adalah tidak menggunakan kait, melainkan menggunakan filter dan atribut git. Apa yang ini memungkinkan Anda lakukan, adalah pengaturan, pada setiap mesin yang Anda kembangkan, seperangkat filter yang akan menghapus ruang ekstra ekstra putih dan garis kosong tambahan di akhir file sebelum membuatnya. Kemudian siapkan file .gitattributes yang menyatakan jenis file yang harus diterapkan filter. Filter memiliki dua fase, cleanyang diterapkan saat menambahkan file ke indeks, dansmudge yang diterapkan saat menambahkannya ke direktori yang berfungsi.

Beri tahu git Anda untuk mencari file atribut global

Pertama, beri tahu konfigurasi global Anda untuk menggunakan file atribut global:

git config --global core.attributesfile ~/.gitattributes_global

Buat filter global

Sekarang, buat filter:

git config --global filter.fix-eol-eof.clean fixup-eol-eof %f
git config --global filter.fix-eol-eof.smudge cat
git config --global filter.fix-eol-eof.required true

Tambahkan sihir skrip sed

Akhirnya, letakkan fixup-eol-eof skrip di suatu tempat di jalur Anda, dan buat agar dapat dieksekusi. Script menggunakan sed untuk melakukan beberapa pengeditan dengan cepat (menghapus spasi dan kosong di akhir baris, dan baris kosong di luar file)

fixup-eol-eof akan terlihat seperti ini:

#!/bin/bash
sed -e 's/[  ]*$//' -e :a -e '/^\n*$/{$d;N;ba' -e '}' $1

intisari saya ini

Beri tahu git jenis file untuk menerapkan filter Anda yang baru dibuat

Terakhir, buat atau buka ~ / .gitattributes_global di editor favorit Anda dan tambahkan baris seperti:

pattern attr1 [attr2 [attr3 […]]]

Jadi jika kita ingin memperbaiki masalah spasi putih, untuk semua file sumber c kita, kita akan menambahkan baris yang terlihat seperti ini:

*.c filter=fix-eol-eof

Diskusi filter

Filter memiliki dua fase, fase bersih yang diterapkan ketika ada hal-hal yang ditambahkan ke indeks atau diperiksa, dan fase noda ketika git memasukkan barang ke direktori kerja Anda. Di sini, noda kami hanya menjalankan konten melalui catperintah yang seharusnya membuat mereka tidak berubah, dengan pengecualian mungkin menambahkan karakter baris baru tambahan jika tidak ada satu di akhir file. Perintah bersih adalah penyaringan spasi putih yang saya buat bersama dari catatan di http://sed.sourceforge.net/sed1line.txt . Tampaknya itu harus dimasukkan ke dalam skrip shell, saya tidak tahu bagaimana cara menyuntikkan perintah sed, termasuk sanitasi dari garis ekstra yang asing di akhir file langsung ke file git-config. (Kamu BISAmenyingkirkan trailing kosong, namun, tanpa perlu script sed terpisah, hanya mengatur filter.fix-eol-eofuntuk sesuatu seperti sed 's/[ \t]*$//' %fmana \tadalah tab yang sebenarnya, dengan menekan tab.)

Requir = true menyebabkan kesalahan untuk dinaikkan jika terjadi kesalahan, untuk menjaga Anda keluar dari masalah.

Maafkan saya jika bahasa saya tentang git tidak tepat. Saya pikir saya memiliki pemahaman yang cukup baik tentang konsep-konsep tetapi saya masih belajar terminologi.


Pendekatan yang menarik. +1
VonC

Terima kasih @VonC! Saya juga ingin menggunakan kesempatan ini untuk menunjukkan bahwa atribut git dapat dikonfigurasikan dalam basis per-repisitory dalam .gitfolder daripada secara global, yang mungkin lebih masuk akal.
zbeekman

9

Saya menulis kait pra-komit ini, yang hanya menghilangkan spasi putih dari garis yang telah Anda ubah / tambahkan, karena saran sebelumnya cenderung membuat komit yang tidak dapat dibaca jika file target memiliki terlalu banyak spasi pada spasi putih.

#!/bin/sh

if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
   against=HEAD
else
   # Initial commit: diff against an empty tree object
   against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

IFS='
'

files=$(git diff-index --check --cached $against -- | sed '/^[+-]/d' | perl -pe 's/:[0-9]+:.*//' | uniq)
for file in $files ; do
    diff=$(git diff --cached $file)
    if test "$(git config diff.noprefix)" = "true"; then
        prefix=0
    else
        prefix=1
    fi
    echo "$diff" | patch -R -p$prefix
    diff=$(echo "$diff" | perl -pe 's/[ \t]+$// if m{^\+}')
    out=$(echo "$diff" | patch -p$prefix -f -s -t -o -)
    if [ $? -eq 0 ]; then
        echo "$diff" | patch -p$prefix -f -t -s
    fi
    git add $file
done

1
Menarik. +1. Lihat jawaban saya yang lain untuk menghitung pohon yang kosong.
VonC

1
Ide bagus, ini persis yang saya inginkan. Namun, berhati-hatilah saat menggunakan ini! Bagi saya di OSX dan git versi 2.3.5 itu menghapus semua penambahan tetapi perubahan tidak berkomitmen saya telah dipentaskan. Saya masih akan tertarik pada solusi yang berfungsi untuk ini.
Casper

9

Silakan coba saya pre-komit kait , dapat otomatis mendeteksi trailing spasi dan menghapusnya . Terima kasih!

itu bisa bekerja di bawah GitBash(windows), Mac OS X and Linux!


Foto:

$ git commit -am "test"
auto remove trailing whitespace in foobar/main.m!
auto remove trailing whitespace in foobar/AppDelegate.m!
[master 80c11fe] test
1 file changed, 2 insertions(+), 2 deletions(-)

1
Menarik. +1. Saya telah merujuk kait Anda dalam jawaban saya sendiri
VonC

@VonC Terima kasih atas afirmasi Anda! Untuk '.md', saya hanya menemukan git commit -no-verify, ada saran?
lelaki tua

Saya lebih suka membuat kait dapat mendeteksi .mdfile dan tidak menghapus spasi putih, daripada meminta pengguna akhir untuk menambahkan --no-verifyopsi pada git commit.
VonC

Gagal jika melakukan file / direktori yang dimulai dengan +atau-
Rody Oldenhuis

6

Ini versi ubuntu + mac os x yang kompatibel:

#!/bin/sh
#

# A git hook script to find and fix trailing whitespace
# in your commits. Bypass it with the --no-verify option
# to git-commit
#

if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
  against=HEAD
else
  # Initial commit: diff against an empty tree object
  against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | (sed -r 's/:[0-9]+:.*//' > /dev/null 2>&1 || sed -E 's/:[0-9]+:.*//') | uniq` ; do
  # Fix them!
  (sed -i 's/[[:space:]]*$//' "$FILE" > /dev/null 2>&1 || sed -i '' -E 's/[[:space:]]*$//' "$FILE")
  git add "$FILE"
done

# Now we can commit
exit

Selamat bersenang-senang


Sepertinya satu-satunya perbedaan antara Anda dan milik saya adalah bahwa Anda memeriksa bahwa sebenarnya akan mengganti sesuatu sebelum menulis ulang file ... Saya tidak yakin itu penting karena git tidak melakukan perubahan yang tidak benar-benar mengubah apa pun. Saya kira itu sedikit lebih aman, tetapi juga sedikit lebih lambat, dan saya lebih suka kejelasan tidak mengulangi regex dua kali pada satu baris. De gustibus non disputandum est!
AlexChaffee

tidak ada perbedaan adalah bahwa versi ini menggunakan sintaks ubuntu terlebih dahulu dan (jika gagal) sesudahnya osx satu.
sdepold

1
i diedit posting sdepold, itu harus dapat juga mengizinkan spasi putih dalam nama file sekarang.
imme

5

Sedang memikirkan hal ini hari ini. Inilah yang akhirnya saya lakukan untuk proyek java:

egrep -rl ' $' --include *.java *  | xargs sed -i 's/\s\+$//g'

3

Untuk pengguna Teks Sublim .

Atur mengikuti dengan benar di pengaturan Anda -Pengguna konfigurasi.

"trim_trailing_white_space_on_save": true


1
Apakah ini cara untuk mengatur ini berdasarkan jenis file? Saya memiliki *.md(penurunan harga) file yang bergantung pada "" (trailing spasi ganda) untuk menandai yang sederhana <br />, dan pengaturan itu tampaknya berlaku untuk semua file, termasuk yang saya tidak ingin menghapus spasi tambahan.
VonC

@VonC Ada hierarki tentang bagaimana konfigurasi diterapkan lebih detail di sini, stackoverflow.com/questions/16983328/... semoga membantu
Haris Krajina

2

for-loop untuk file menggunakan variabel $ IFS shell. dalam skrip yang diberikan, nama file dengan karakter di dalamnya yang juga ada dalam variabel $ IFS akan dilihat sebagai dua file berbeda di for-loop. Skrip ini memperbaikinya: pengubah mode multiline seperti yang diberikan sed-manual tampaknya tidak berfungsi secara default di kotak ubuntu saya, jadi saya mencari implementasi yang berbeda dan menemukan ini dengan label iterasi, pada dasarnya ia hanya akan memulai substitusi pada baris terakhir file jika saya sudah memahaminya dengan benar.

#!/bin/sh
#

# A git hook script to find and fix trailing whitespace
# in your commits. Bypass it with the --no-verify option
# to git-commit
#

if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

SAVEIFS="$IFS"
# only use new-line character as seperator, introduces EOL-bug?
IFS='
'
# Find files with trailing whitespace
for FILE in $(
    git diff-index --check --cached $against -- \
    | sed '/^[+-]/d' \
    | ( sed -r 's/:[0-9]+:.*//' || sed -E 's/:[0-9]+:.*//' ) \
    | uniq \
)
do
# replace whitespace-characters with nothing
# if first execution of sed-command fails, try second one( MacOSx-version)
    (
        sed -i ':a;N;$!ba;s/\n\+$//' "$FILE" > /dev/null 2>&1 \
        || \
        sed -i '' -E ':a;N;$!ba;s/\n\+$//' "$FILE" \
    ) \
    && \
# (re-)add files that have been altered to git commit-tree
#   when change was a [:space:]-character @EOL|EOF git-history becomes weird...
    git add "$FILE"
done
# restore $IFS
IFS="$SAVEIFS"

# exit script with the exit-code of git's check for whitespace-characters
exec git diff-index --check --cached $against --

[1] pola sed-subsition: Bagaimana saya bisa mengganti baris baru (\ n) menggunakan sed? .


2

Ini tidak menghapus spasi putih secara otomatis sebelum komit, tetapi cukup mudah untuk memberikan efek. Saya menempatkan skrip perl berikut dalam file bernama git-wsf (git whitespace fix) dalam dir di $ PATH sehingga saya bisa:

git wsf | SH

dan menghapus semua spasi putih hanya dari baris file yang mendapat laporan sebagai diff.

#! /bin/sh
git diff --check | perl -x $0
exit

#! /usr/bin/perl

use strict;

my %stuff;
while (<>) {
    if (/trailing whitespace./) {
        my ($file,$line) = split(/:/);
        push @{$stuff{$file}},$line;
    }
}

while (my ($file, $line) = each %stuff) {
    printf "ex %s <<EOT\n", $file;
    for (@$line) {
        printf '%ds/ *$//'."\n", $_;
    }
    print "wq\nEOT\n";
}

0

Sedikit terlambat tetapi karena ini mungkin membantu seseorang di luar sana, ini dia.

Buka file dalam VIM. Untuk mengganti tab dengan spasi putih, ketikkan baris perintah vim berikut ini

:%s#\t#    #gc

Untuk menyingkirkan spasi putih tertinggal lainnya

:%s#\s##gc

Ini cukup banyak melakukannya untuk saya. Itu membosankan jika Anda memiliki banyak file untuk diedit. Tapi saya merasa lebih mudah daripada kait pre-commit dan bekerja dengan banyak editor.


Jika membosankan - dan jika Anda memiliki cadangan dari apa yang akan Anda edit - maka saya sering hanya menggunakan sed untuk mengubah tab ke spasi: sed -i 's|\t| |g' filenames(spasi di posisi ganti). Perhatikan bahwa Anda dapat menggunakan find untuk mendapatkan nama file Anda. Jika Anda belum memikirkan cara mendapatkan cadangan itu, saya biasanya hanya mengkomit semuanya dan kemudian 'membatalkan' komit dengan soft reset kembali ke tempat saya; kadang-kadang saya menambahkan semuanya ke pohon tetapi tidak melakukan, dan kadang-kadang saya menggunakan simpanan / berlaku (bukan pop!). Jika saya merasa cemas, saya rsync seluruh pohon saya ke lokasi yang aman sebelum ikut campur ...
bijak

0

Untuk menghapus spasi spasi di akhir baris dalam file dengan mudah, gunakan ed:

test -s file &&
   printf '%s\n' H ',g/[[:space:]]*$/s///' 'wq' | ed -s file

-1

Ini mungkin tidak akan secara langsung menyelesaikan masalah Anda, tetapi Anda mungkin ingin mengaturnya melalui git-config di ruang proyek Anda yang sebenarnya, yang mengedit ./.git/config sebagai kebalikan dari ~ / .gitconfig. Senang menjaga pengaturan konsisten di antara semua anggota proyek.

git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"

3
afaik, pengaturan di dalam. git tidak dibagi dengan orang lain; mereka khusus untuk repo lokal Anda
AlexChaffee
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.