Git rimuove automaticamente gli spazi vuoti finali prima di eseguire il commit


220

Sto usando git con il mio team e vorrei rimuovere le modifiche agli spazi bianchi dai miei diff, dai log, dalle fusioni, ecc. Sto assumendo che il modo più semplice per farlo sarebbe che Git rimuovesse automaticamente gli spazi bianchi finali (e altri errori degli spazi bianchi) ) da tutti i commit man mano che vengono applicati.

Ho provato ad aggiungere quanto segue per ~/.gitconfigfile ma non faccio nulla quando commetto. Forse è progettato per qualcosa di diverso. Qual è la soluzione?

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

Sto usando il rubino nel caso qualcuno abbia qualche idea specifica sul rubino. La formattazione automatica del codice prima del commit sarebbe il passo successivo, ma questo è un problema difficile e non causa davvero un grosso problema.


Se la direttiva core.whitespace non risolve i tuoi problemi, puoi anche cambiare l'hook pre-commit (.git / hooks / pre-commit) per trovarli e risolverli per te. Vedi questo post per una descrizione dettagliata.
Volk,

2
Sono stato frustrato da simili errori di spazio bianco e soluzioni parziali e ho scritto un'utilità flessibile e abbastanza completa di funzionalità che può correggere o semplicemente segnalare errori di spazio bianco che i sistemi di controllo della versione bedevil: Whitespace Total Fixer su Github (si scusa se è troppo auto-promozionale)
Dan Lenski,

Risposte:


111

Tali impostazioni ( core.whitespacee apply.whitespace) non sono lì per rimuovere gli spazi bianchi finali ma per:

  • core.whitespace: rilevali e genera errori
  • apply.whitespace: e rimuoverli, ma solo durante la patch, non "sempre automaticamente"

Credo che git hook pre-commitfarebbe un lavoro migliore per questo (include la rimozione di spazi bianchi finali)


Si noti che in qualsiasi momento è possibile scegliere di non eseguire l' pre-commithook:

  • temporaneamente: git commit --no-verify .
  • permanentemente: cd .git/hooks/ ; chmod -x pre-commit

Avvertenza: per impostazione predefinita, uno pre-commitscript (come questo ) non ha una funzione "rimuovi trailing", ma una funzione di "avvertimento" come:

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

Tuttavia, potresti creare un pre-commithook migliore , soprattutto se consideri che:

Il commit in Git con solo alcune modifiche aggiunte all'area di gestione temporanea comporta comunque una revisione "atomica" che potrebbe non essere mai esistita come copia funzionante e potrebbe non funzionare .


Ad esempio, oldman propone in un'altra risposta un pre-commithook che rileva e rimuove gli spazi bianchi.
Dato che quell'hook ottiene il nome del file di ciascun file, consiglierei di fare attenzione a determinati tipi di file: non si desidera rimuovere gli spazi vuoti finali nei .mdfile (markdown)!


1
Si scopre che git può essere convinto a correggere gli spazi bianchi nella copia di lavoro tramite apply.whitespace, ingannando git nel trattare le modifiche della copia di lavoro come patch. Vedi la mia risposta qui sotto .
ntc2

> "non vuoi rimuovere gli spazi vuoti finali nei file .md (markdown)" - Perché? Qual è lo scopo di trascinare gli spazi bianchi nei file markdown? Ho notato che alcuni .editorconfigfile hanno una regola specifica per questo.
friederbluemle,

5
@friederbluemle a seconda del tipo di markdown, un doppio spazio finale indica <br>: github.com/FriendsOfPHP/PHP-CS-Fixer/issues/…
VonC

L'impostazione core.whitespacesu trailing-spacecon git confignon genera errori quando si esegue il commit in git2.5.0.
Karl Richter,

43

Puoi ingannare Git nel fissare lo spazio bianco per te, ingannando Git nel trattare le tue modifiche come una patch. Contrariamente alle soluzioni "hook pre-commit", queste soluzioni aggiungono comandi Git per il fissaggio degli spazi bianchi.

Sì, questi sono hack.


Soluzioni robuste

I seguenti alias Git sono presi dal mio~/.gitconfig .

Per "robusto" intendo che questi alias funzionano senza errori, facendo la cosa giusta, indipendentemente dal fatto che l'albero o l'indice siano sporchi. Tuttavia, non funzionano se git rebase -iè già in corso un interattivo ; consultare my~/.gitconfig per ulteriori controlli se ti interessa questo caso d'angolo, in cui il git add -etrucco descritto alla fine dovrebbe funzionare.

Se vuoi eseguirli direttamente nella shell, senza creare un alias Git, copia e incolla tutto tra le doppie virgolette (supponendo che la tua shell sia simile a Bash).

Correggi l'indice ma non l'albero

Il seguente fixwsalias Git corregge tutti gli errori degli spazi bianchi nell'indice, se presenti, ma non tocca l'albero:

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

L'idea è di eseguire git fixwsprima git commitse si verificano errori di spazio nell'indice.

Correggi l'indice e l'albero

Il seguente fixws-global-tree-and-indexalias Git corregge tutti gli errori degli spazi bianchi nell'indice e nella struttura, se presenti:

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

Per correggere anche gli spazi bianchi nei file senza versione, fare

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

Soluzioni semplici ma non robuste

Queste versioni sono più facili da copiare e incollare, ma non fanno la cosa giusta se le loro condizioni secondarie non sono soddisfatte.

Correggi il sottoalbero radicato nella directory corrente (ma reimposta l'indice se non è vuoto)

Usando git add -eper "modificare" le patch con l'editor delle identità ::

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

Correggi e conserva l'indice (ma non riesce se l'albero è sporco o l'indice è vuoto)

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

Correggi l'albero e l'indice (ma reimposta l'indice se non è vuoto)

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

Spiegazione del export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .trucco

Prima di apprendere il git rebase --whitespace=fixtrucco da questa risposta, stavo usando il git addtrucco più complicato ovunque.

Se lo facessimo manualmente:

  1. Impostare apply.whitespacesu fix(devi farlo solo una volta):

    git config apply.whitespace fix
    

    Questo dice a Git di correggere gli spazi bianchi nelle patch .

  2. Convinci Git a trattare le tue modifiche come una patch :

    git add -up .
    

    Premi a+ enterper selezionare tutte le modifiche per ciascun file. Riceverai un avviso su Git che risolve i tuoi errori di spazio bianco.
    ( git -c color.ui=auto diffa questo punto rivela che le modifiche non indicizzate sono esattamente gli errori degli spazi bianchi).

  3. Rimuovi gli errori degli spazi bianchi dalla tua copia di lavoro:

    git checkout .
    
  4. Ripristina le modifiche (se non sei pronto a impegnarle):

    git reset
    

Il GIT_EDITOR=:mezzo da utilizzare :come editor e come comando :è l'identità.


1
L'ho appena testato su Windows: funziona benissimo nel prompt dei comandi di DOS: set VISUAL= && git add -ue . && git checkout .nota ' .' usato con git add: questo a causa di git1.8.3
VonC,

@VonC Non disattiverà VISUAL in modo permanente, il che potrebbe, ad esempio, causare un successivo utilizzo di un git commiteditor errato? Avvolgo la VISUAL=parte in una subshell nella mia versione unix sopra per evitarlo, ma non so se DOS abbia subshells.
ntc2,

1
Grazie per l'ottimo hack! Cordiali saluti, se è stato core.editorimpostato, l'esportazione VISUALnon ha alcun effetto poiché l'impostazione di configurazione ha la precedenza per man git-var. Per sovrascriverlo devi GIT_EDITOR=:invece esportare .
Nick Felt,

1
Inoltre, ho modificato la mia versione fixwsper fallire velocemente se sei già in un rebase interattivo poiché altrimenti morirà sulla git rebase --whitespace=fixlinea e ti lascerà in uno stato strano. Ho preso in prestito da questa domanda e ho appena aggiunto un caso in più prima del se: 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: L'ho adattato in un hook pre-commit
Ian Kelling il

29

Ho trovato un hook pre-commit git che rimuove gli spazi bianchi finali .

#!/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
La seconda sedchiamata ( sed -r 's/:[0-9]+:.*//') potrebbe essere sostituita con cut -f1 -d:. Questo dovrebbe funzionare allo stesso modo su entrambe le piattaforme basate su Linux e BSD.
Ihor Kaharlichenko,

2
@IhorKaharlichenko: in realtà, l'uso cutnon è sicuro come il secondo sed: il taglio fallirà nel caso (altamente improbabile) di nomi di file che contengono ":". Potresti usare awk 'NF>2{NF-=2}1'per essere al sicuro
MestreLion

1
A proposito, se sei su Windows (msysgit) e usi core.autocrlf=true, potresti voler aggiungere dos2unix -D "$FILE"all'interno del ciclo for, dopo sed. Altrimenti, cambierà tutti i CRLF in LF emettendo solo sed.
jakub.g

49
Fare git adddentro un gancio di commit mi sembra piuttosto malvagio. Cosa succede se si sta eseguendo la gestione temporanea / il commit parziale di un file? Non vuoi che il file completo venga impegnato alle tue spalle, vero?
Stefaan,

19

Su Mac OS (o, probabilmente, su qualsiasi BSD), i parametri del comando sed devono essere leggermente diversi. Prova questo:

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

Salvare questo file come .git/hooks/pre-commit- o cercare quello che è già lì e incollare il blocco inferiore da qualche parte al suo interno. E ricorda anche a chmod a+xquesto.

O per uso globale (tramite hook di commit di Git - impostazioni globali ) è possibile inserirlo $GIT_PREFIX/git-core/templates/hooks(dove GIT_PREFIX è / usr o / usr / local o / usr / share o / opt / local / share) ed eseguire git initall'interno dei repository esistenti.

Secondo git help init:

L'esecuzione di git init in un repository esistente è sicura. Non sovrascriverà le cose che sono già lì. Il motivo principale per la riesecuzione di git init è la raccolta di nuovi modelli aggiunti.


7
Questo hook non modifica il file di lavoro e sovrascrive l'indice con il file di lavoro modificato? Se dovessi "git add -p" per costruire il tuo indice, questo hook di commit lo spazzerebbe via.
Matthew Dutton,

2
Sì, probabilmente hai ragione. Qualcuno potrebbe dover riscrivere questo script per usare git hash-object -we git update-index(ri) inserire il file munged direttamente nell'indice. Qualcuno molto coraggioso.
AlexChaffee,

11

Preferirei lasciare questo compito al tuo editor preferito.

Basta impostare un comando per rimuovere gli spazi finali durante il salvataggio.


2
In vim puoi farlo con: autocmd BufWritePre .cpp, .c, *. H:% / \ s \ + $ // e
Robert Massaioli,

3
Mi dispiace, ho annullato il commento sopra prima di testarlo. Manca una "s" dopo il segno di percentuale e sposta il cursore se viene trovato uno spazio bianco e rimuove l'ultimo modello di ricerca. Vedi vim.wikia.com/wiki/Remove_unwanted_spaces per alternative migliori.
Seth Johnson,

1
In emacs è Mx delete-trailing-whitespace.
Mauvis Ledford,

2
Meglio ancora, per emacs, imposta un hook per eliminare gli spazi vuoti finali prima di salvare aggiungendoli (add-hook 'before-save-hook 'delete-trailing-whitespace)al tuo .emacsfile. Trucchi per gli spazi bianchi di Emacs
Duncan Parkes,

1
Uso (aggiungi-hook 'before-save-hook' whitespace-cleanup) che converte anche le schede in spazi.
Nils Fagerburg,

10

Utilizzo degli attributi git e impostazione dei filtri con git config

OK, questa è una nuova strategia per risolvere questo problema ... Il mio approccio è non usare alcun hook, ma piuttosto usare filtri e attributi git. Ciò che ti consente di fare è impostare, su ogni macchina su cui sviluppi, un set di filtri che rimuoveranno lo spazio bianco finale in eccesso e le righe vuote extra alla fine dei file prima di eseguirne il commit. Quindi imposta un file .gitattributes che indica a quali tipi di file il filtro deve essere applicato. I filtri hanno due fasi, cleanche viene applicata quando si aggiungono file all'indice e smudgeche viene applicata quando li si aggiunge alla directory di lavoro.

Di 'al tuo git di cercare un file di attributi globale

Innanzitutto, comunica alla tua configurazione globale di utilizzare un file di attributi globali:

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

Crea filtri globali

Ora crea il filtro:

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

Aggiungi la magia di scripting di sed

Infine, metti lo fixup-eol-eofscript da qualche parte sul tuo percorso e rendilo eseguibile. Lo script usa sed per eseguire alcune modifiche al volo (rimuovere spazi e spazi vuoti alla fine delle linee e linee vuote estranee alla fine del file)

fixup-eol-eof dovrebbe apparire così:

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

il mio senso di questo

Indica a git a quali tipi di file applicare il filtro appena creato

Infine, crea o apri ~ / .gitattributes_global nel tuo editor preferito e aggiungi righe come:

pattern attr1 [attr2 [attr3 […]]]

Quindi, se vogliamo risolvere il problema degli spazi bianchi, per tutti i nostri file di origine c aggiungeremo una riga simile a questa:

*.c filter=fix-eol-eof

Discussione sul filtro

Il filtro ha due fasi, la fase pulita che viene applicata quando le cose vengono aggiunte all'indice o archiviate e la fase sfumata quando git inserisce elementi nella directory di lavoro. Qui, la nostra sfumatura sta semplicemente eseguendo i contenuti attraverso il catcomando che dovrebbe lasciarli invariati, con l'eccezione di aggiungere eventualmente un carattere di nuova riga finale se non ce n'era uno alla fine del file. Il comando clean è il filtro degli spazi bianchi che ho messo insieme dalle note su http://sed.sourceforge.net/sed1line.txt . Sembra che debba essere inserito in uno script di shell, non sono riuscito a capire come iniettare il comando sed, incluso il risanamento delle righe extra estranee alla fine del file direttamente nel file git-config. ( PUOIsbarazzarsi di spazi vuoti finali, tuttavia, senza la necessità di uno script sed separato, basta impostare filter.fix-eol-eofsu qualcosa come sed 's/[ \t]*$//' %fdove \tè una scheda effettiva, premendo la scheda.)

Request = true provoca la generazione di un errore se qualcosa va storto, per tenerti fuori dai guai.

Per favore, perdonami se la mia lingua riguardante git è imprecisa. Penso di avere una buona conoscenza dei concetti, ma sto ancora imparando la terminologia.


Approccio interessante +1
VonC,

Grazie @VonC! Vorrei anche cogliere l'occasione per sottolineare che gli attributi git possono essere configurati in base al repository nella .gitcartella anziché a livello globale, il che potrebbe avere più senso.
zbeekman,

9

Ho scritto questo hook pre-commit, che rimuove solo lo spazio bianco finale dalle righe che hai modificato / aggiunto, poiché i suggerimenti precedenti tendono a creare commit illeggibili se i file di destinazione hanno troppo spazio bianco finale.

#!/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
Interessante. +1. Vedi la mia altra risposta per calcolare l'albero vuoto.
VonC,

1
Buona idea, questo è esattamente quello che vorrei. Tuttavia, fai attenzione quando lo usi! Per me su OSX e git versione 2.3.5 fa saltare tutte le modifiche aggiunte ma non confermate che ho messo in scena. Sarei comunque interessato a una soluzione funzionante per questo.
Casper,

9

Prova i miei hook pre-commit , è in grado di rilevare automaticamente il trailing-whitespace e rimuoverlo . Grazie!

può funzionare sotto GitBash(windows), Mac OS X and Linux!


Istantanea:

$ 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
Interessante. +1. Ho fatto riferimento al tuo hook nella mia risposta
VonC

@VonC Grazie per la tua affermazione! Al ".md", ho trovato solo git commit -no-verifyqualche suggerimento?
Oldman,

Preferirei che l'hook fosse in grado di rilevare il .mdfile e non rimuovere gli spazi bianchi, piuttosto che chiedere all'utente finale di aggiungere --no-verifyun'opzione su git commit.
VonC,

Non riesce se si esegue il commit di un file / directory che inizia con un +o-
Rody Oldenhuis il

6

Ecco una versione compatibile di 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

Divertiti


Sembra che l'unica differenza tra la tua e la mia sia che controlli che sed sostituirà effettivamente qualcosa prima di riscrivere il file ... Non sono sicuro che sia importante poiché git non commette modifiche che non cambiano nulla. Suppongo che sia leggermente più sicuro, ma anche leggermente più lento, e preferisco la chiarezza di non ripetere due volte le regex su una riga. De gustibus non disputandum est!
AlexChaffee,

no la differenza è che la versione utilizza prima la sintassi ubuntu e (se ciò fallisce) dopo quella osx.
venduto il

1
ho modificato il post di sdepold, ora dovrebbe essere in grado di consentire anche spazi bianchi nei nomi dei file.
imme

5

Stavo pensando a questo oggi. Questo è tutto ciò che ho finito per fare per un progetto Java:

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

3

Per gli utenti di Sublime Text .

Impostare correttamente quanto segue nella configurazione di Impostazione dell'utente .

"trim_trailing_white_space_on_save": true


1
È un modo per impostare questo per tipo di file? Ho *.md(markdown) file che si basano su "" (spazi doppi finali) per contrassegnare un semplice <br />e quell'impostazione sembra applicarsi a tutti i file, compresi quelli che non voglio rimuovere gli spazi finali.
VonC,

@VonC Esiste una gerarchia su come applicare la configurazione qui maggiori dettagli, stackoverflow.com/questions/16983328/… speriamo che sia d'aiuto
Haris Krajina,

2

il ciclo for per i file utilizza la variabile shell $ IFS. nello script dato, i nomi dei file con un carattere che è anche nella variabile $ IFS saranno visti come due file diversi nel for-loop. Questo script lo risolve: il modificatore in modalità multilinea come dato sed-manual non sembra funzionare di default sul mio Ubuntu Box, quindi ho cercato una diversa implementazione e l'ho trovato con un'etichetta iterante, essenzialmente inizierà solo la sostituzione sul ultima riga del file se l'ho capito correttamente.

#!/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] modello sed-subsition: come posso sostituire una newline (\ n) usando sed? .


2

Questo non rimuove automaticamente gli spazi bianchi prima di un commit, ma è abbastanza facile da effettuare. Ho inserito il seguente script perl in un file chiamato git-wsf (correzione dello spazio bianco git) in una directory in $ PATH, così posso:

git wsf | sh

e rimuove tutto lo spazio bianco solo dalle righe di file che riportano i report come 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

Leggermente in ritardo, ma poiché questo potrebbe aiutare qualcuno là fuori, ecco qui.

Apri il file in VIM. Per sostituire le schede con spazi bianchi, digitare quanto segue nella riga di comando di vim

:%s#\t#    #gc

Per sbarazzarsi di altri spazi bianchi finali

:%s#\s##gc

Questo l'ha fatto praticamente per me. È noioso se hai molti file da modificare. Ma l'ho trovato più facile degli hook pre-commit e lavorare con più editor.


Se diventa noioso - e se hai un backup di ciò che stai per modificare - spesso uso semplicemente sed per cambiare le schede in spazi: sed -i 's|\t| |g' filenames(spazi nella posizione di sostituzione). Nota che puoi usare find per ottenere i tuoi nomi di file. Se non hai pensato a come ottenere quel backup, di solito eseguo il commit di tutto e quindi "annullo" il commit con un ripristino software al punto in cui mi trovo; a volte aggiungo tutto all'albero ma non commetto, a volte uso lo stash / apply (non pop!). Se mi sento ansioso, risincronizzo il mio intero albero in un luogo sicuro prima di immischiarmi ...
saggio

0

Per eliminare gli spazi vuoti finali alla fine della riga in un file in modo portabile, utilizzare ed:

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

-1

Questo probabilmente non risolverà direttamente il tuo problema, ma potresti volerli impostare tramite git-config nello spazio del tuo progetto reale, che modifica ./.git/config invece di ~ / .gitconfig. Bello mantenere le impostazioni coerenti tra tutti i membri del progetto.

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

3
inoltre, le impostazioni all'interno di .git non sono condivise con nessun altro; sono specifici per il tuo repository locale
AlexChaffee,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.