Faça o git remover automaticamente o espaço em branco à direita antes de confirmar

220

Estou usando o git com minha equipe e gostaria de remover alterações de espaço em branco dos meus diffs, logs, mesclagens etc. Estou assumindo que a maneira mais fácil de fazer isso seria o git remover automaticamente o espaço em branco à direita (e outros erros de espaço em branco) ) de todas as confirmações conforme são aplicadas.

Eu tentei adicionar o seguinte ao ~/.gitconfigarquivo, mas ele não faz nada quando eu confirmo. Talvez tenha sido projetado para algo diferente. Qual a solução?

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

Estou usando ruby, caso alguém tenha alguma idéia específica sobre rubi. A formatação automática de código antes da confirmação seria o próximo passo, mas esse é um problema difícil e realmente não está causando um grande problema.

mloughran
fonte
Se a diretiva core.whitespace não corrigir seus problemas, você também poderá alterar o gancho de pré-confirmação (.git / hooks / pre-commit) para encontrar e corrigi-los para você. Veja este post para uma descrição detalhada.
VolkA
2
Fiquei frustrado com erros semelhantes de espaço em branco e soluções parciais e escrevi um utilitário flexível e bastante completo que pode corrigir ou simplesmente relatar erros de espaço em branco que perturbam os sistemas de controle de versão: Whitespace Total Fixer no Github (desculpas se isso for muito autopromocional)
Dan Lenski

Respostas:

111

Essas configurações ( core.whitespacee apply.whitespace) não existem para remover o espaço em branco à direita, mas para:

  • core.whitespace: detectá-los e gerar erros
  • apply.whitespace: e retire-os, mas apenas durante o patch, nem sempre "automaticamente"

Eu acredito que o git hook pre-commitfaria um trabalho melhor para isso (inclui remover espaços em branco à direita)


Observe que a qualquer momento você pode optar por não executar o pre-commitgancho:

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

Aviso: por padrão, um pre-commitscript (como este ) não possui um recurso "remover à direita", mas um recurso de "aviso" como:

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

No entanto, você pode criar um pre-commitgancho melhor , especialmente quando considera que:

A confirmação no Git com apenas algumas alterações adicionadas à área de preparação ainda resulta em uma revisão "atômica" que pode nunca ter existido como uma cópia de trabalho e pode não funcionar .


Por exemplo, oldman propõe em outra resposta um pre-commitgancho que detecta e remove os espaços em branco.
Como esse gancho obtém o nome de cada arquivo, eu recomendaria ter cuidado com certos tipos de arquivos: você não deseja remover o espaço em branco à direita nos .mdarquivos (descontos)!

VonC
fonte
1
Acontece que o git pode ser convencido a corrigir espaços em branco na sua cópia de trabalho apply.whitespace, enganando o git a tratar suas alterações na cópia de trabalho como um patch. Veja minha resposta abaixo .
Ntc2 13/03/2013
> "você não deseja remover o espaço em branco à direita nos arquivos .md (markdown)" - Por que isso? Qual é o objetivo de rastrear espaços em branco nos arquivos de remarcação? Notei que alguns .editorconfigarquivos têm uma regra específica para isso.
Friederbluemle
5
@friederbluemle, dependendo do tipo de remarcação, um espaço duplo à direita indica <br>: github.com/FriendsOfPHP/PHP-CS-Fixer/issues/…
VonC
Definir core.whitespacepara trailing-spacecom git confignão gera erro ao confirmar no git2.5.0.
Karl Richter
43

Você pode induzir o Git a corrigir o espaço em branco para você, enganando o Git a tratar suas alterações como um patch. Ao contrário das soluções "gancho de pré-confirmação", essas soluções adicionam comandos de correção de espaço em branco ao Git.

Sim, estes são hacks.


Soluções robustas

Os seguintes aliases do Git são retirados do meu~/.gitconfig .

Por "robusto", quero dizer que esses aliases são executados sem erros, fazendo a coisa certa, independentemente de a árvore ou o índice estarem sujos. No entanto, eles não funcionam se uma interativa git rebase -ijá estiver em andamento; consulte o meu~/.gitconfig para verificações adicionais se você se importa com este caso de canto, onde o git add -etruque descrito no final deve funcionar.

Se você deseja executá-los diretamente no shell, sem criar um alias do Git, basta copiar e colar tudo entre aspas duplas (assumindo que o seu shell seja do tipo Bash).

Corrija o índice, mas não a árvore

O seguinte fixwsalias do Git corrige todos os erros de espaço em branco no índice, se houver, mas não toca na árvore:

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

A ideia é executar git fixwsantes git commitse houver erros de espaço em branco no índice.

Corrija o índice e a árvore

O fixws-global-tree-and-indexalias do Git a seguir corrige todos os erros de espaço em branco no índice e na árvore, se houver:

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

Para também corrigir espaços em branco em arquivos não versionados, faça

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

Soluções simples, mas não robustas

Essas versões são mais fáceis de copiar e colar, mas não fazem a coisa certa se suas condições colaterais não forem atendidas.

Corrija a subárvore com raiz no diretório atual (mas redefina o índice se não estiver vazio)

Usando git add -epara "editar" os patches com o editor de identidade ::

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

Corrija e preserve o índice (mas falhará se a árvore estiver suja ou o índice estiver vazio)

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

Corrija a árvore e o índice (mas redefine o índice se não estiver vazio)

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

Explicação do export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .truque

Antes de aprender sobre o git rebase --whitespace=fixtruque desta resposta, eu estava usando o git addtruque mais complicado em todos os lugares.

Se o fizermos manualmente:

  1. Defina apply.whitespacecomo fix(você só precisa fazer isso uma vez):

    git config apply.whitespace fix
    

    Isso diz ao Git para corrigir espaços em branco nos patches .

  2. Convença o Git a tratar suas alterações como um patch :

    git add -up .
    

    Pressione a+ enterpara selecionar todas as alterações para cada arquivo. Você receberá um aviso sobre o Git corrigindo os erros de espaço em branco.
    ( git -c color.ui=auto diffneste momento, revela que suas alterações não indexadas são exatamente os erros de espaço em branco).

  3. Remova os erros de espaço em branco da sua cópia de trabalho:

    git checkout .
    
  4. Traga de volta suas alterações (se você não estiver pronto para confirmá-las):

    git reset
    

O GIT_EDITOR=:meio de usar :como editor e como comando :é a identidade.

ntc2
fonte
1
Acabei de testar no Windows: isso funciona muito bem em um prompt de comando do DOS: set VISUAL= && git add -ue . && git checkout .Observe o ' .' usado com git add: isso é devido ao git1.8.3
VonC
@VonC Isso não desativará o VISUAL permanentemente, o que pode, por exemplo, fazer com que um uso subseqüente git commituse o editor errado? Envolvo a VISUAL=parte em um subshell na versão unix acima para evitar isso, mas não sei se o DOS tem subshells.
Ntc2 26/07
1
Obrigado pelo ótimo hack! Para sua informação, se você core.editorconfigurou, a exportação VISUALnão terá efeito, pois a configuração terá precedência por man git-var. Para substituir isso, você precisa exportar GIT_EDITOR=:.
perfil completo de Nick Felt
1
Além disso, aprimorei minha versão fixwspara falhar rapidamente, se você já estiver em uma recuperação interativa, pois, caso contrário, ela morrerá na git rebase --whitespace=fixlinha e deixará você em um estado estranho. I emprestado esta pergunta e acabou de adicionar um caso extra antes do caso: 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: Eu adaptado isso em um gancho pré-comprometer
Ian Kelling
29

Encontrei um gancho de pré-confirmação do git que remove os espaços em branco à direita .

#!/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
fonte
3
A segunda sedinvocação ( sed -r 's/:[0-9]+:.*//') pode ser substituída por cut -f1 -d:. Isso deve funcionar da mesma forma nas plataformas Linux e BSD.
Ihor Kaharlichenko
2
@IhorKaharlichenko: na verdade, o uso cutnão é tão seguro quanto o segundo sed: o corte falhará no caso (altamente improvável) de nomes de arquivos que contêm ":". Você poderia usar awk 'NF>2{NF-=2}1'para ser seguro
MestreLion
1
BTW, se você estiver no Windows (msysgit) e core.autocrlf=trueestiver usando , poderá adicionar dos2unix -D "$FILE"dentro do loop for, depois do sed. Caso contrário, ele mudará todos os CRLFs para LFs emitindo apenas sed.
31412 jokub.g
49
Fazer git adddentro de um gancho de confirmação parece muito ruim para mim. E se você estiver fazendo teste / confirmação parcial de um arquivo? Você não quer que o arquivo completo seja confirmado pelas costas, não é?
Stefaan
19

No Mac OS (ou, provavelmente, em qualquer BSD), os parâmetros do comando sed precisam ser um pouco diferentes. Tente o seguinte:

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

Salve este arquivo como .git/hooks/pre-commit- ou procure o que já está lá e cole o pedaço inferior em algum lugar dentro dele. E lembre-se chmod a+xdisso também.

Ou para uso global (via Git commit hooks - configurações globais ), você pode colocá-lo $GIT_PREFIX/git-core/templates/hooks(onde GIT_PREFIX é / usr ou / usr / local ou / usr / share ou / opt / local / share) e executar git initdentro de seus repositórios existentes.

De acordo com git help init:

A execução do git init em um repositório existente é segura. Ele não substituirá as coisas que já estão lá. O principal motivo para executar novamente o git init é pegar os modelos adicionados recentemente.

AlexChaffee
fonte
7
Esse gancho não está modificando o arquivo de trabalho e substituindo o índice pelo arquivo de trabalho modificado? Se você 'git add -p' construísse seu índice, esse gancho de commit iria acabar com isso.
Matthew Dutton
2
Sim, você provavelmente está certo. Alguém pode precisar reescrever esse script para usar git hash-object -we git update-index(re) inserir o arquivo munged diretamente no índice. Alguém muito corajoso.
AlexChaffee
11

Prefiro deixar essa tarefa para o seu editor favorito.

Basta definir um comando para remover os espaços finais ao salvar.

Giacomo
fonte
2
No vim você pode fazer isso com: BufWritePre autocmd .cpp, .c, * h:% / \ s \ + $ // e.
Robert Massaioli
3
Desculpe, votei no comentário acima antes de testá-lo. Há um "s" ausente após o sinal de porcentagem, e ele moverá o cursor se houver espaço em branco e removerá o último padrão de pesquisa. Consulte vim.wikia.com/wiki/Remove_unwanted_spaces para obter melhores alternativas.
Seth Johnson
1
No emacs, é Mx delete-trailing-whitespace.
Mauvis Ledford
2
Melhor ainda, para o emacs, defina um gancho para excluir o espaço em branco à direita antes de salvar adicionando (add-hook 'before-save-hook 'delete-trailing-whitespace)ao seu .emacsarquivo. Emacs espaços em branco truques
Duncan Parkes
1
Eu uso (add-hook 'before-save-hook' whitespace-cleanup) que também converte guias em espaços.
Nils Fagerburg #
10

Usando atributos git e configuração de filtros com git config

OK, esta é uma nova abordagem para resolver esse problema ... Minha abordagem é não usar ganchos, mas usar filtros e atributos git. O que isso permite, é configurar, em cada máquina em que você desenvolve, um conjunto de filtros que eliminam o espaço em branco e as linhas em branco no final dos arquivos antes de enviá-los. Em seguida, configure um arquivo .gitattributes que indique em quais tipos de arquivos o filtro deve ser aplicado. Os filtros têm duas fases, cleanque são aplicadas ao adicionar arquivos ao índice e smudgeque são aplicadas ao adicioná-los ao diretório de trabalho.

Diga ao seu git para procurar um arquivo de atributos globais

Primeiro, diga à sua configuração global para usar um arquivo de atributos globais:

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

Crie filtros globais

Agora, crie o 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

Adicione a mágica do script sed

Por fim, coloque o fixup-eol-eofscript em algum lugar do seu caminho e torne-o executável. O script usa sed para fazer algumas edições dinâmicas (remova espaços e espaços em branco no final das linhas e linhas em branco estranhas no final do arquivo)

fixup-eol-eof deve ficar assim:

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

minha essência disso

Diga ao git quais tipos de arquivo aplicar o filtro recém-criado

Por fim, crie ou abra ~ / .gitattributes_global no seu editor favorito e adicione linhas como:

pattern attr1 [attr2 [attr3 […]]]

Portanto, se quisermos corrigir o problema de espaço em branco, para todos os nossos arquivos de origem c, adicionaremos uma linha parecida com esta:

*.c filter=fix-eol-eof

Discussão do filtro

O filtro tem duas fases, a fase limpa, que é aplicada quando as coisas são adicionadas ao índice ou registradas, e a fase de borrar, quando o git coloca coisas no seu diretório de trabalho. Aqui, nossa mancha está apenas executando o conteúdo através do catcomando que deve mantê-lo inalterado, com a exceção de possivelmente adicionar um caractere de nova linha à direita, se não houver um no final do arquivo. O comando clean é a filtragem de espaço em branco que juntei das notas em http://sed.sourceforge.net/sed1line.txt . Parece que deve ser colocado em um shell script, não consegui descobrir como injetar o comando sed, incluindo o saneamento de linhas extras estranhas no final do arquivo diretamente no arquivo git-config. (Você PODEse livrar dos espaços em branco à direita, no entanto, sem a necessidade de um script sed separado, defina-o filter.fix-eol-eofcomo algo como sed 's/[ \t]*$//' %fonde \testá uma guia real, pressionando tab.)

A exigência = true faz com que um erro seja gerado se algo der errado, para mantê-lo longe de problemas.

Por favor, perdoe-me se minha linguagem sobre o git for imprecisa. Acho que tenho uma compreensão bastante boa dos conceitos, mas ainda estou aprendendo a terminologia.

zbeekman
fonte
Abordagem interessante. +1
VonC
Obrigado @VonC! Eu também quero aproveitar esta oportunidade para salientar que os atributos git podem ser configurados em uma base per-repisitory no.git pasta e não globalmente, o que pode fazer mais sentido.
Zbeekman
9

Eu escrevi esse gancho de pré-confirmação, que remove apenas o espaço em branco à direita das linhas que você alterou / adicionou, pois as sugestões anteriores tendem a criar confirmações ilegíveis se os arquivos de destino tiverem muito espaço em branco à direita.

#!/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
fonte
1
Interessante. +1. Veja minha outra resposta para calcular a árvore vazia.
VonC
1
Boa ideia, é exatamente isso que eu gostaria. No entanto, tenha cuidado ao usar isso! Para mim, no OSX e na versão 2.3.5 do git, ele afasta qualquer alteração adicional, mas não confirmada, que eu tenha realizado. Eu ainda estaria interessado em uma solução funcional para isso.
Casper
9

Por favor, tente meus ganchos pré-confirmação , ele pode detectar automaticamente o espaço em branco à direita e removê-lo . Obrigado!

pode funcionar em baixo GitBash(windows), Mac OS X and Linux!


Instantâneo:

$ 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(-)
Velhote
fonte
1
Interessante. +1. Eu referenciei o seu gancho na minha própria resposta
VonC 28/03
@VonC Obrigado pela sua afirmação! Para o '.md', eu só encontrei git commit -no-verify, alguma sugestão?
oldman 28/03
Prefiro tornar o gancho capaz de detectar .mdarquivos e não remover os espaços em branco, em vez de pedir ao usuário final para adicionar uma --no-verifyopção no git commit.
VonC 28/03
Falha ao confirmar um arquivo / diretório que começa com um +ou-
Rody Oldenhuis
6

Aqui está uma versão compatível com 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

Diverta-se

distribuído
fonte
Parece que a única diferença entre a sua e a minha é que você verifique se o sed realmente substituirá algo antes de reescrever o arquivo ... Não tenho certeza de que isso importe, já que o git não comete alterações que na verdade não alteram nada. Suponho que seja marginalmente mais seguro, mas também marginalmente mais lento, e prefiro a clareza de não repetir as regexes duas vezes em uma linha. De gustibus non disputandum est!
AlexChaffee
não, a diferença é que a versão está usando a sintaxe do ubuntu primeiro e (se isso falhar) depois da osx.
sdepold
1
Se eu editei a postagem de sdepold, ele também deve permitir espaços em branco nos nomes de arquivos agora.
Imme
5

Estava pensando sobre isso hoje. Isso é tudo o que acabei fazendo em um projeto java:

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

Para usuários de texto sublime .

Defina o seguinte corretamente na sua configuração User-Setting .

"trim_trailing_white_space_on_save": true

Haris Krajina
fonte
1
É uma maneira de definir isso por tipo de arquivo? Eu tenho *.mdarquivos (markdown) que dependem de "" (espaços duplos à direita) para marcar um simples <br />, e essa configuração parece se aplicar a todos os arquivos, incluindo os que eu não quero remover os espaços à direita.
VonC
@VonC Há hierarquia sobre como a configuração é aplicada mais detalhes aqui, stackoverflow.com/questions/16983328/... espero que ajude
Haris Krajina
2

o loop for para arquivos usa a variável de shell $ IFS. no script fornecido, os nomes de arquivos com um caractere que também esteja na variável $ IFS serão vistos como dois arquivos diferentes no loop for. Este script o corrige: o modificador de modo multilinha, dado o sed-manual, não parece funcionar por padrão na minha caixa do ubuntu, então procurei uma implementação diferente e a encontrei com um rótulo iterativo, essencialmente ele só começará a substituição no última linha do arquivo, se eu entendi corretamente.

#!/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] padrão sed-subsition: como substituir uma nova linha (\ n) usando sed? .

immeëmosol
fonte
2

Isso não remove os espaços em branco automaticamente antes de uma confirmação, mas é bastante fácil de efetuar. Coloquei o seguinte script perl em um arquivo chamado git-wsf (correção de espaço em branco do git) em um diretório em $ PATH para que eu possa:

git wsf | sh

e remove todo o espaço em branco apenas das linhas de arquivos que o git reporta como um 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";
}
davidc
fonte
0

Um pouco tarde, mas como isso pode ajudar alguém lá fora, aqui vai.

Abra o arquivo no VIM. Para substituir guias por espaços em branco, digite o seguinte na linha de comando do vim

:%s#\t#    #gc

Para se livrar de outros espaços em branco à direita

:%s#\s##gc

Isso praticamente fez por mim. É entediante se você tiver muitos arquivos para editar. Mas achei mais fácil do que pré-confirmar ganchos e trabalhar com vários editores.

hriddle
fonte
Se for tedioso - e se você tiver um backup do que está prestes a editar -, geralmente uso o sed para alterar as guias para os espaços: sed -i 's|\t| |g' filenames(espaços na posição de substituição). Observe que você pode usar o find para obter seus nomes de arquivos. Se você ainda não pensou em como obter esse backup, normalmente apenas confirmo tudo e depois 'desfazo' o commit com uma redefinição suave de volta para onde estou; às vezes eu adiciono tudo à árvore, mas não faço commit, e às vezes eu uso o stash / apply (não pop!). Se me sinto ansioso, sincronizo toda a minha árvore em um local seguro antes de me intrometer ...
sáb
0

Para excluir espaços em branco à direita no final da linha em um arquivo, use ed:

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

Provavelmente, isso não resolverá diretamente o seu problema, mas você pode configurá-los via git-config no espaço real do projeto, que edita ./.git/config em oposição a ~ / .gitconfig. É bom manter as configurações consistentes entre todos os membros do projeto.

git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"
esposa
fonte
3
afaik, as configurações no .git não são compartilhadas com mais ninguém; Eles são específicos para o seu repo locais
AlexChaffee