Niech git automatycznie usunie końcowe białe znaki przed zatwierdzeniem

220

Używam git z moim zespołem i chciałbym usunąć zmiany białych znaków z moich różnic, logów, scaleń itp. Zakładam, że najłatwiejszym sposobem na to byłoby git, aby automatycznie usunąć końcowe białe znaki (i inne błędy białych znaków) ) ze wszystkich zatwierdzeń po ich zastosowaniu.

Próbowałem dodać następujące do ~/.gitconfigpliku, ale nic nie robi po zatwierdzeniu. Może jest przeznaczony do czegoś innego. Jakie jest rozwiązanie

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

Używam rubinu na wypadek, gdyby ktoś miał jakieś pomysły na ruby. Następnym krokiem byłoby automatyczne formatowanie kodu przed zatwierdzeniem, ale jest to trudny problem i tak naprawdę nie powoduje dużego problemu.

mloughran
źródło
Jeśli dyrektywa core.whitespace nie rozwiązuje twoich problemów, możesz również zmienić przechwytywanie przed zatwierdzeniem (.git / hooks / pre-commit), aby je znaleźć i naprawić. Zobacz ten post, aby uzyskać szczegółowy opis.
VolkA
2
Byłem sfrustrowany podobnymi błędami białych znaków i częściowymi rozwiązaniami, i napisałem elastyczne i dość kompletne narzędzie, które może naprawić lub po prostu zgłosić błędy białych znaków, które działają na systemach kontroli wersji: Whitespace Total Fixer na Github (przeprasza, jeśli jest to zbyt autopromocyjne)
Dan Lenski

Odpowiedzi:

111

Te ustawienia ( core.whitespacei apply.whitespace) nie służą do usuwania końcowych białych znaków, ale do:

  • core.whitespace: wykryj je i zgłaszaj błędy
  • apply.whitespace: i usuń je, ale tylko podczas łatania, nie „zawsze automatycznie”

Uważam, git hook pre-commitże lepiej by to zrobiło (obejmuje usunięcie spacji końcowych)


Pamiętaj, że w dowolnym momencie możesz nie uruchamiać pre-commithaka:

  • tymczasowo: git commit --no-verify .
  • na stałe: cd .git/hooks/ ; chmod -x pre-commit

Ostrzeżenie: domyślnie pre-commitskrypt (taki jak ten ) nie ma funkcji „usuń końcowy”, ale funkcję „ostrzegającą”, taką jak:

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

Możesz jednak zbudować lepszy pre-commithak , zwłaszcza jeśli weźmiesz pod uwagę, że:

Zatwierdzenie w Git z kilkoma zmianami dodanymi do obszaru przejściowego wciąż powoduje „atomową” wersję, która mogła nigdy nie istnieć jako kopia robocza i może nie działać .


Na przykład, Oldman proponuje w innym odpowiedź na pre-commithak , który wykrywa i usunąć spacje.
Ponieważ ten haczyk pobiera nazwę każdego pliku, zalecam ostrożność w przypadku niektórych typów plików: nie chcesz usuwać końcowych białych znaków w .mdplikach (przecena)!

VonC
źródło
1
Okazuje się, że git można przekonać do naprawienia białych znaków w kopii roboczej za pomocą apply.whitespace, nakłaniając git do traktowania zmian kopii roboczej jako łatki. Zobacz moją odpowiedź poniżej .
ntc2
> „nie chcesz usuwać końcowych białych znaków w plikach .md (Markdown)” - dlaczego? Jaki jest cel zamiany białych znaków w plikach przecen? Zauważyłem, że niektóre .editorconfigpliki mają określoną regułę.
friederbluemle
5
@friederbluemle w zależności od rodzaju przeceny, końcowe podwójne spacje wskazują <br>: github.com/FriendsOfPHP/PHP-CS-Fixer/issues/…
VonC
Ustawienie core.whitespacena trailing-spacez git confignie powoduje błędu podczas zatwierdzania w wersji git2.5.0.
Karl Richter
43

Możesz oszukać Gita, aby naprawił dla Ciebie spację, oszukiwając Gita, by traktował twoje zmiany jako łatkę. W przeciwieństwie do rozwiązań „przechwytujących przed zatwierdzeniem”, rozwiązania te dodają polecenia Git do naprawiania białych znaków.

Tak, to są hacki.


Solidne rozwiązania

Poniższe aliasy Git pochodzą ode mnie~/.gitconfig .

Przez „solidny” rozumiem, że te aliasy są uruchamiane bezbłędnie, wykonując właściwe czynności, niezależnie od tego, czy drzewo lub indeks są brudne. Nie działają jednak, jeśli interaktywna git rebase -ijest już w toku; zobacz moje~/.gitconfig dodatkowe kontrole, jeśli zależy ci na tym rogu, w którym git add -etrik opisany na końcu powinien zadziałać.

Jeśli chcesz uruchomić je bezpośrednio w powłoce, bez tworzenia aliasu Git, po prostu skopiuj i wklej wszystko między podwójnymi cudzysłowami (zakładając, że twoja powłoka jest podobna do Bash).

Napraw indeks, ale nie drzewo

Poniższy fixwsalias Git naprawia wszystkie błędy białych znaków w indeksie, jeśli występują, ale nie dotyka drzewa:

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

Chodzi o to, aby uruchomić git fixwswcześniej, git commitjeśli w indeksie występują błędy białych znaków.

Napraw indeks i drzewo

Poniższy fixws-global-tree-and-indexalias Git naprawia wszystkie błędy białych znaków w indeksie i drzewie, jeśli występują:

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

Aby również naprawić białe znaki w niewersjonowanych plikach, wykonaj:

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

Proste, ale nie solidne rozwiązania

Te wersje są łatwiejsze do skopiowania i wklejenia, ale nie robią tego dobrze, jeśli ich warunki boczne nie są spełnione.

Napraw poddrzewa zakorzenione w bieżącym katalogu (ale resetuje indeks, jeśli nie jest pusty)

Używanie git add -edo „edycji” poprawek za pomocą edytora tożsamości ::

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

Napraw i zachowaj indeks (ale zawiedzie, jeśli drzewo jest brudne lub indeks jest pusty)

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

Napraw drzewo i indeks (ale resetuje indeks, jeśli nie jest pusty)

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

Wyjaśnienie export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .sztuczki

Zanim dowiedziałem się o git rebase --whitespace=fixsztuczce z tej odpowiedzi,git add wszędzie używałem bardziej skomplikowanej sztuczki.

Jeśli zrobiliśmy to ręcznie:

  1. Ustawić apply.whitespacena fix(trzeba tylko to zrobić raz):

    git config apply.whitespace fix
    

    To każe Gitowi naprawić białe znaki w łatkach .

  2. Przekonaj Gita, aby potraktował twoje zmiany jako łatkę :

    git add -up .
    

    Naciśnij a+, enteraby wybrać wszystkie zmiany dla każdego pliku. Otrzymasz ostrzeżenie o naprawianiu błędów spacji przez Git.
    ( git -c color.ui=auto diffw tym momencie ujawnia, że ​​twoje niezindeksowane zmiany są dokładnie błędami spacji).

  3. Usuń błędy białych znaków z kopii roboczej:

    git checkout .
    
  4. Przywróć zmiany (jeśli nie jesteś gotowy, aby je zatwierdzić):

    git reset
    

Te GIT_EDITOR=:środki do wykorzystania :jako redaktor, a jako polecenie :jest tożsamość.

ntc2
źródło
1
Właśnie przetestowałem to w systemie Windows: działa dobrze w wierszu polecenia systemu DOS: set VISUAL= && git add -ue . && git checkout .Uwaga : „ .” używane z git add: to jest z powodu git1.8.3
VonC
@VonC Czy to nie rozbroi VISUAL na stałe, co może np. Spowodować późniejsze użycie git commitniewłaściwego edytora? Owinęłam tę VISUAL=część w podpowłoce w mojej wersji unix powyżej, aby tego uniknąć, ale nie wiem, czy DOS ma podpowłoki.
ntc2
1
Dzięki za świetny hack! Do Twojej wiadomości, jeśli core.editorustawiłeś, eksportowanie VISUALnie ma żadnego efektu, ponieważ ustawienie konfiguracji ma pierwszeństwo dla man git-var. Aby to zmienić, musisz wyeksportować GIT_EDITOR=:.
Nick Felt
1
Również poprawiłem moją wersję, fixwsby szybko się nie udawała, jeśli jesteś już w interaktywnej bazie, ponieważ w przeciwnym razie umrze na git rebase --whitespace=fixlinii i pozostawi cię w dziwnym stanie. Pożyczałem od tego pytania i właśnie dodałem dodatkowy przypadek przed: 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: Zaadaptowałem to do haka przed zatwierdzeniem
Ian Kelling
29

Znalazłem hak wstępnego zatwierdzenia git, który usuwa końcowe białe znaki .

#!/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
cmcginty
źródło
3
Drugie sedwywołanie ( sed -r 's/:[0-9]+:.*//') można zastąpić cut -f1 -d:. Powinno to działać tak samo na platformach Linux i BSD.
Ihor Kaharlichenko
2
@IhorKaharlichenko: w rzeczywistości używanie cutnie jest tak bezpieczne, jak drugie sed: cięcie zakończy się niepowodzeniem w (bardzo mało prawdopodobnym) przypadku nazw plików zawierających „:”. Możesz awk 'NF>2{NF-=2}1'być bezpieczny
MestreLion
1
BTW, jeśli korzystasz z systemu Windows (msysgit) i używasz core.autocrlf=true, możesz chcieć dodać dos2unix -D "$FILE"wewnątrz pętli for, po sed. W przeciwnym razie zmieni wszystkie CRLF na LF, wydając tylko sed.
jakub.g
49
Robienie git addwewnątrz haka zatwierdzającego wydaje mi się dość złe. Co się stanie, jeśli wykonujesz częściowe przemieszczanie / zatwierdzanie pliku? Nie chcesz, aby cały plik został popełniony za twoimi plecami, prawda?
Stefaan
19

W systemie Mac OS (lub prawdopodobnie w dowolnym BSD) parametry polecenia sed muszą się nieco różnić. Spróbuj tego:

#!/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

Zapisz ten plik jako .git/hooks/pre-commit - lub poszukaj tego, który już tam jest, i wklej gdzieś w nim dolną porcję. I też o tym pamiętaj chmod a+x.

Lub do użytku globalnego (poprzez haki zatwierdzania Git - ustawienia globalne ) możesz go umieścić $GIT_PREFIX/git-core/templates/hooks(gdzie GIT_PREFIX to / usr lub / usr / local lub / usr / share lub / opt / local / share) i uruchomić git initwewnątrz istniejących repozytoriów.

Według git help init :

Uruchamianie git init w istniejącym repozytorium jest bezpieczne. Nie zastąpi rzeczy, które już tam są. Głównym powodem ponownego uruchomienia git init jest pobranie nowo dodanych szablonów.

AlexChaffee
źródło
7
Czy ten hak nie modyfikuje pliku roboczego i zastępuje indeks zmodyfikowanym plikiem roboczym? Jeśli miałbyś 'git add -p' skonstruować swój indeks, ten hook zatwierdzenia by to zniszczył.
Matthew Dutton
2
Tak, prawdopodobnie masz rację. Może być konieczne przepisanie tego skryptu w celu użycia git hash-object -wi git update-index(ponownego) wstawienia pliku munged bezpośrednio do indeksu. Ktoś bardzo odważny.
AlexChaffee,
11

Wolę pozostawić to zadanie twojemu ulubionemu redaktorowi.

Wystarczy ustawić polecenie, aby usunąć końcowe spacje podczas zapisywania.

Giacomo
źródło
2
W vimie możesz to zrobić za pomocą: autocmd BufWritePre .cpp, .c, *. H:% / \ s \ + $ // e
Robert Massaioli,
3
Przepraszam, przegłosowałem powyższy komentarz przed jego przetestowaniem. Po znaku procentu brakuje „s” i przesunie on kursor, jeśli zostanie znaleziona biała spacja, i usunie ostatni wzorzec wyszukiwania. Zobacz vim.wikia.com/wiki/Remove_unwanted_spaces dla lepszych alternatyw.
Seth Johnson
1
W emacsie jest to Mx delete-trailing-whiteespace.
Mauvis Ledford
2
Jeszcze lepiej, w przypadku emacsa, ustaw hak, aby usunąć końcowe białe znaki przed zapisaniem, dodając (add-hook 'before-save-hook 'delete-trailing-whitespace)do .emacspliku.Sztuczki emacsowe spacjami
Duncan Parkes,
1
Używam (add-hook 'before-save-hook' cleanspace-cleanup), który również przekształca tabulatory w spacje.
Nils Fagerburg
10

Korzystanie z atrybutów git i konfiguracji filtrów z git config

OK, to nowy sposób na rozwiązanie tego problemu… Moje podejście polega na tym, aby nie używać żadnych haczyków, ale raczej używać filtrów i atrybutów git. Pozwala to na skonfigurowanie na każdym komputerze, na którym się rozwijasz, zestawu filtrów, które usuwają dodatkowe końcowe białe spacje i dodatkowe puste linie na końcu plików przed ich zatwierdzeniem. Następnie skonfiguruj plik .gitattributes, który określa typy plików, do których należy zastosować filtr. Filtry mają dwie fazy, cleanktóre są stosowane podczas dodawania plików do indeksu i smudgektóre są stosowane podczas dodawania ich do katalogu roboczego.

Powiedz swojemu gitowi, aby szukał globalnego pliku atrybutów

Po pierwsze, powiedz swojej globalnej konfiguracji, aby używała globalnego pliku atrybutów:

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

Utwórz filtry globalne

Teraz utwórz filtr:

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

Dodaj magię skryptów sed

Na koniec umieść fixup-eol-eof skrypt gdzieś na swojej ścieżce i spraw, aby był wykonywalny. Skrypt używa sed do edycji w locie (usuwanie spacji i odstępów na końcu linii oraz obcych pustych linii na końcu pliku)

fixup-eol-eof powinien wyglądać następująco:

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

moja istota tego

Powiedz git, do jakich typów plików zastosować nowo utworzony filtr

Na koniec utwórz lub otwórz ~ / .gitattributes_global w swoim ulubionym edytorze i dodaj linie takie jak:

pattern attr1 [attr2 [attr3 […]]]

Więc jeśli chcemy naprawić problem z białymi znakami, dla wszystkich naszych plików źródłowych c dodalibyśmy linię wyglądającą tak:

*.c filter=fix-eol-eof

Dyskusja na temat filtra

Filtr ma dwie fazy, fazę czystą, która jest stosowana, gdy rzeczy są dodawane do indeksu lub rejestrowane, oraz fazę rozmazywania, gdy git umieszcza rzeczy w katalogu roboczym. W tym przypadku nasza rozmazanie po prostu uruchamia zawartość za pomocą catpolecenia, które powinno pozostawić je bez zmian, z wyjątkiem ewentualnego dodania końcowego znaku nowej linii, jeśli nie ma go na końcu pliku. Polecenie czyste to filtrowanie białych znaków, które zebrałem razem z notatek na stronie http://sed.sourceforge.net/sed1line.txt, spacji . Wygląda na to, że należy go umieścić w skrypcie powłoki, nie mogłem wymyślić, jak wstrzyknąć komendę sed, w tym oczyścić dodatkowe linie na końcu pliku bezpośrednio do pliku git-config. ( MOŻESZpozbyć się jednak spacji końcowych, bez potrzeby oddzielnego skryptu sed, po prostu ustaw opcję filter.fix-eol-eofna coś, sed 's/[ \t]*$//' %fgdzie \tjest to prawdziwa karta, naciskając tab.)

Wymagana = prawda powoduje, że błąd pojawia się, jeśli coś pójdzie nie tak, aby uniknąć kłopotów.

Proszę wybacz mi, jeśli mój język dotyczący git jest nieprecyzyjny. Myślę, że dość dobrze rozumiem pojęcia, ale wciąż uczę się terminologii.

zbeekman
źródło
Ciekawe podejście +1
VonC
Dzięki @VonC! Chciałbym również skorzystać z okazji, aby wskazać, że atrybuty git można konfigurować dla poszczególnych repozytoriów w .gitfolderze, a nie globalnie, co może mieć większy sens.
zbeekman
9

Napisałem ten haczyk przed zatwierdzeniem, który usuwa tylko końcowe białe znaki z linii, które zmieniłeś / dodałeś, ponieważ poprzednie sugestie mają tendencję do tworzenia nieczytelnych zatwierdzeń, jeśli pliki docelowe mają zbyt dużo końcowych białych znaków.

#!/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
urandom
źródło
1
Ciekawy. +1. Zobacz moją drugą odpowiedź dotyczącą obliczania pustego drzewa.
VonC
1
Dobry pomysł, właśnie tego bym chciał. Należy jednak zachować ostrożność podczas korzystania z tego! Dla mnie na OSX i gicie w wersji 2.3.5 zdmuchuje wszelkie dodane, ale niezaangażowane zmiany, które wprowadziłem. Jednak nadal byłbym zainteresowany działającym rozwiązaniem tego problemu.
Casper
9

Spróbuj moich haków przed zatwierdzeniem , może automatycznie wykryć końcowe białe spacje i je usunąć . Dziękuję Ci!

może działać pod GitBash(windows), Mac OS X and Linux!


Migawka:

$ 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(-)
starzec
źródło
1
Ciekawy. +1. Nawiązałem do twojego haka w mojej własnej odpowiedzi
VonC
@VonC Dziękujemy za potwierdzenie! Do „.md” znalazłem tylko git commit -no-verifyjakieś sugestie?
oldman
Wolę, aby hak mógł wykryć .mdplik, a nie usuwać białe znaki, zamiast prosić użytkownika końcowego o dodanie --no-verifyopcji na git commit.
VonC
Nie powiedzie się, jeśli plik / katalog zaczyna się od +lub-
Rody Oldenhuis
6

Oto wersja kompatybilna z Ubuntu + Mac OS X:

#!/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

baw się dobrze

sdepold
źródło
Wygląda na to, że jedyną różnicą między twoją a moją jest to, że sprawdzasz, czy sed faktycznie coś zastąpi przed przepisaniem pliku ... Nie jestem pewien, czy to ważne, ponieważ git nie dokonuje zmian, które tak naprawdę niczego nie zmieniają. Podejrzewam, że jest marginalnie bezpieczniejszy, ale także nieznacznie wolniejszy i wolę przejrzystość, aby nie powtarzać wyrażeń regularnych dwa razy w jednym wierszu. De gustibus non disputandum est!
AlexChaffee,
nie ma różnicy, że wersja używa najpierw składni ubuntu, a następnie (jeśli to się nie powiedzie) OSX.
sdepold
1
Zredagowałem post sdepolda, teraz powinno być teraz dozwolone także spacje w nazwach plików.
imme
5

Myślałem o tym dzisiaj. To wszystko, co skończyłem dla projektu Java:

egrep -rl ' $' --include *.java *  | xargs sed -i 's/\s\+$//g'
Grant Murphy
źródło
3

Dla użytkowników Sublime Text .

Ustaw odpowiednio następujące ustawienia konfiguracji użytkownika .

"trim_trailing_white_space_on_save": true

Haris Krajina
źródło
1
Czy to sposób na ustawienie tego według typu pliku? Mam *.mdpliki (przeceny), które polegają na „” (końcowe podwójne spacje) do oznaczania prostego <br />, i to ustawienie wydaje się mieć zastosowanie do wszystkich plików, w tym tych, których nie chcę usuwać końcowych spacji.
VonC
@VonC Istnieje hierarchia stosowania konfiguracji. Więcej szczegółów tutaj, stackoverflow.com/questions/16983328/... mam nadzieję, że to pomoże
Haris Krajina,
2

pętla for dla plików używa zmiennej powłoki $ IFS. w danym skrypcie nazwy plików ze znakiem, który również znajduje się w zmiennej $ IFS, będą widoczne jako dwa różne pliki w pętli for. Ten skrypt to naprawia: modyfikator trybu wielowierszowego, jak podano w instrukcji sed, nie wydaje się domyślnie działać na moim polu ubuntu, więc szukałem innej implementacji i znalazłem to z iterującą etykietą, w zasadzie zacznie on zastępować na ostatni wiersz pliku, jeśli dobrze go zrozumiałem.

#!/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] wzorzec subskrybcji: jak mogę zamienić znak nowej linii (\ n) za pomocą sed? .

immeëmosol
źródło
2

To nie usuwa automatycznie białych znaków przed zatwierdzeniem, ale jest dość łatwe do wykonania. Umieszczam następujący skrypt perla w pliku o nazwie git-wsf (git whitespace fix) w katalogu w $ PATH, dzięki czemu mogę:

git wsf | sh

i usuwa wszystkie białe znaki tylko z linii plików, które git raporty jako różnicę.

#! /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";
}
davidc
źródło
0

Nieco późno, ale ponieważ może to komuś pomóc, oto jest.

Otwórz plik w VIM. Aby zamienić tabulatory na białe znaki, wpisz następujące polecenie w wierszu poleceń vim

:%s#\t#    #gc

Aby pozbyć się innych spacji końcowych

:%s#\s##gc

To prawie dla mnie to zrobiło. To nużące, jeśli masz wiele plików do edycji. Ale uznałem, że jest to łatwiejsze niż przechwytywanie z wyprzedzeniem i praca z wieloma edytorami.

hriddle
źródło
Jeśli stanie się to żmudne - i jeśli masz kopię zapasową tego, co zamierzasz edytować - wtedy często używam sed do zmiany tabulatorów na spacje: sed -i 's|\t| |g' filenames(spacje w pozycji zastępowania). Pamiętaj, że możesz użyć find, aby uzyskać nazwy plików. Jeśli nie zastanawiałeś się, jak uzyskać tę kopię zapasową, zwykle po prostu zatwierdzam wszystko, a następnie „cofam” zatwierdzenie miękkim resetowaniem z powrotem tam, gdzie jestem; czasami dodam wszystko do drzewa, ale nie zatwierdzam, a czasem używam skrytki / zastosowania (nie pop!). Jeśli czuję lęk, synchronizuję całe drzewo w bezpiecznym miejscu, zanim wtrącę się ...
mędrzec
0

Aby przenośnie usunąć końcowe białe znaki na końcu wiersza w pliku, użyj ed:

test -s file &&
   printf '%s\n' H ',g/[[:space:]]*$/s///' 'wq' | ed -s file
nat
źródło
-1

Prawdopodobnie nie rozwiąże to bezpośrednio twojego problemu, ale możesz chcieć ustawić je za pomocą git-config w twojej rzeczywistej przestrzeni projektu, która edytuje ./.git/config w przeciwieństwie do ~ / .gitconfig. Miło jest zachować spójność ustawień wśród wszystkich członków projektu.

git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"
bojo
źródło
3
afaik, ustawienia w .git nie są udostępniane nikomu; są specyficzne dla twojego lokalnego repozytorium
AlexChaffee,