Заставить git автоматически удалять конечные пробелы перед фиксацией

220

Я использую git с моей командой и хотел бы удалить изменения пробелов из моих различий, журналов, слияний и т. Д. Я предполагаю, что самый простой способ сделать это - git автоматически удалить конечные пробелы (и другие ошибки пробелов) ) из всех коммитов по мере их применения.

Я попытался добавить следующее к ~/.gitconfigфайлу, но он ничего не делает, когда я фиксирую. Может быть, он предназначен для чего-то другого. Какое решение?

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

Я использую ruby ​​на тот случай, если у кого-нибудь есть какие-то конкретные идеи. Следующим шагом будет автоматическое форматирование кода перед фиксацией, но это сложная проблема, которая не вызывает больших проблем.

mloughran
источник
Если директива core.whitespace не устраняет ваши проблемы, вы также можете изменить хук предварительной фиксации (.git / hooks / pre-commit), чтобы найти и исправить их за вас. Смотрите этот пост для подробного описания.
VolkA
2
Я был разочарован подобными ошибками пробелов и частичными решениями и написал гибкую и достаточно полнофункциональную утилиту, которая может исправлять или просто сообщать об ошибках пробелов, которые портят системы контроля версий: Whitespace Total Fixer на Github (извиняюсь, если это слишком самореклама)
Дэн Ленски

Ответы:

111

Эти настройки ( core.whitespaceи apply.whitespace) предназначены не для удаления конечных пробелов, а для:

  • core.whitespace: обнаружить их и вызвать ошибки
  • apply.whitespace: и лишить их, но только во время патча, а не "всегда автоматически"

Я считаю, что git hook pre-commitэто сделало бы лучшую работу для этого (в том числе удаление конечных пробелов)


Обратите внимание, что в любой момент вы можете не запускать pre-commitхук:

  • временно: git commit --no-verify .
  • постоянно: cd .git/hooks/ ; chmod -x pre-commit

Предупреждение: по умолчанию, pre-commitскрипт (как этот ), имеет не функцию «удаления висячего», а функцию «предупреждения», такую ​​как:

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

Однако вы можете создать лучший pre-commitхук , особенно если учесть, что:

Фиксация в Git только с некоторыми изменениями, добавленными в область подготовки, все еще приводит к «атомарной» ревизии, которая, возможно, никогда не существовала в качестве рабочей копии и может не работать .


Например, Олдман предлагает в другой ответ на pre-commitкрючок , который детектирует и удалить пробелы.
Так как этот хук получает имя файла каждого файла, я бы рекомендовал быть осторожным с определенным типом файлов: вы не хотите удалять конечные пробелы в .md(уценке) файлах!

VonC
источник
1
Оказывается, git можно убедить исправить пробелы в вашей рабочей копии apply.whitespace, обманув git, чтобы он рассматривал изменения рабочей копии как патч. Смотрите мой ответ ниже .
ntc2
> «Вы не хотите удалять конечные пробелы в файлах .md (markdown)» - Почему это так? Какова цель пробела пробелов в файлах уценки? Я заметил, что у некоторых .editorconfigфайлов есть определенное правило для этого.
Friederbluemle
5
@friederbluemle, в зависимости от типа уценки, завершающий двойной пробел указывает <br>: github.com/FriendsOfPHP/PHP-CS-Fixer/issues/…
VonC
Установка core.whitespaceв trailing-spacewith git configне вызывает ошибку при gitфиксации в 2.5.0.
Карл Рихтер
43

Вы можете обмануть Git, чтобы исправить пробелы для вас, обманув Git, рассматривая ваши изменения как патч. В отличие от решений «pre-commit hook», эти решения добавляют в Git команды исправления пробелов.

Да, это хаки.


Надежные решения

Следующие псевдонимы Git взяты из моего~/.gitconfig .

Под «устойчивым» я подразумеваю, что эти псевдонимы работают без ошибок, делая правильные вещи, независимо от того, являются ли дерево или индекс грязными. Тем не менее, они не работают, если интерактив git rebase -iуже выполняется; см. мои~/.gitconfig дополнительные проверки, если вам небезразличен этот угловой случай, где git add -eописанный в конце прием должен работать.

Если вы хотите запустить их непосредственно в оболочке, не создавая псевдоним Git, просто скопируйте и вставьте все в двойные кавычки (при условии, что ваша оболочка похожа на Bash).

Исправить индекс, но не дерево

Следующий fixwsпсевдоним Git исправляет все пробельные ошибки в индексе, если таковые имеются, но не затрагивает дерево:

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

Идея состоит в том, чтобы запускаться git fixwsраньше, git commitесли у вас есть ошибки пробела в индексе.

Исправить индекс и дерево

Следующий fixws-global-tree-and-indexпсевдоним Git исправляет все ошибки пробелов в индексе и дереве, если они есть:

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

Чтобы также исправить пробелы в неверсионных файлах, выполните

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

Простые, но не надежные решения

Эти версии легче копировать и вставлять, но они не делают правильных вещей, если их побочные условия не выполняются.

Исправьте поддерево с корнем в текущем каталоге (но сбрасывает индекс, если он не пустой)

Использование git add -eдля «редактирования» патчей с помощью редактора идентичности ::

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

Исправить и сохранить индекс (но не работает, если дерево грязное или индекс пустой)

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

Исправьте дерево и индекс (но сбрасывает индекс, если он не пустой)

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

Объяснение export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .уловки

Прежде чем я узнал об git rebase --whitespace=fixуловке из этого ответа, я использовал более сложную git addуловку везде.

Если мы сделали это вручную:

  1. Установите apply.whitespaceв fix(вы должны сделать это только один раз):

    git config apply.whitespace fix
    

    Это говорит Git исправлять пробелы в патчах .

  2. Убедите Git рассматривать ваши изменения как патч :

    git add -up .
    

    Нажмите a+, enterчтобы выбрать все изменения для каждого файла. Вы получите предупреждение о том, что Git исправляет ваши пробельные ошибки.
    ( git -c color.ui=auto diffв этот момент обнаруживается, что ваши неиндексированные изменения являются именно ошибками пробелов).

  3. Удалите ошибки пробелов из вашей рабочей копии:

    git checkout .
    
  4. Верните ваши изменения (если вы не готовы их зафиксировать):

    git reset
    

В GIT_EDITOR=:средстве для использования в :качестве редактора, и как команда :является тождественным.

NTC2
источник
1
Я только что проверил это в Windows: это прекрасно работает в командной строке DOS: set VISUAL= && git add -ue . && git checkout .Обратите внимание на ' .', используемый с git add: это из-за git1.8.3
VonC
@ VonC Разве это не отключит VISUAL навсегда, что может, например, привести к последующему использованию git commitнеправильного редактора? Я оборачиваю VISUAL=часть в подоболочку в моей версии Unix выше, чтобы избежать этого, но я не знаю, есть ли в DOS подоболочки.
ntc2
1
Спасибо за отличный взлом! К вашему сведению, если вы core.editorустановили, то экспорт не VISUALимеет никакого эффекта, потому что параметр конфигурации имеет приоритет по man git-var. Чтобы переопределить это, вам нужно экспортировать GIT_EDITOR=:вместо этого.
Ник Фелт
1
Кроме того, я настроил свою версию fixwsна провал быстро, если вы уже находитесь в интерактивном ребазинге, так как иначе он умрет на git rebase --whitespace=fixлинии и оставит вас в странном состоянии. Я позаимствовал этот вопрос и просто добавил дополнительный случай перед тем, как: 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 \ ...
Ник Фетт
1
К вашему сведению: я адаптировал это в ловушку перед фиксацией
Ян Келлинг
29

Я нашел git pre-commit hook, который удаляет завершающие пробелы .

#!/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
источник
3
Второй sedвызов ( sed -r 's/:[0-9]+:.*//') можно заменить на cut -f1 -d:. Это должно работать одинаково на платформах Linux и BSD.
Игорь Кахарличенко
2
@IhorKaharlichenko: на самом деле использование cutне так безопасно, как второе sed: вырезать не удастся в (крайне маловероятном) случае имен файлов, содержащих «:». Вы можете использовать, awk 'NF>2{NF-=2}1'чтобы быть в безопасности
MestreLion
1
Кстати, если вы в Windows (msysgit) и используете core.autocrlf=true, вы можете добавить dos2unix -D "$FILE"внутри цикла for, после sed. В противном случае он изменит все CRLF на LF, выдав только sed.
jakub.g
49
Выполнение git addвнутри коммита хук кажется мне довольно злым. Что делать, если вы делаете частичную подготовку / фиксацию файла? Вы же не хотите, чтобы весь файл был передан вам за спину?
Стефаан
19

В Mac OS (или, скорее всего, в любом BSD) параметры команды sed должны немного отличаться. Попробуй это:

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

Сохраните этот файл как .git/hooks/pre-commit- или найдите тот, который уже там, и вставьте нижний блок где-нибудь внутри него. И помните, chmod a+xэто тоже.

Или для глобального использования (через Git commit hooks - глобальные настройки ) вы можете поместить его $GIT_PREFIX/git-core/templates/hooks(где GIT_PREFIX - / usr или / usr / local или / usr / share или / opt / local / share) и запустить git initвнутри существующих репозиториев.

По словам git help init:

Запуск git init в существующем хранилище безопасен. Это не перезапишет то, что уже есть. Основная причина перезапуска git init - это выбор новых добавленных шаблонов.

AlexChaffee
источник
7
Разве этот хук не изменяет рабочий файл и не перезаписывает индекс измененным рабочим файлом? Если бы вы создали git add -p для создания вашего индекса, этот хук коммитов сорвал бы это.
Мэтью Даттон
2
Да, вы, вероятно, правы. Кто-то, возможно, придется переписать этот сценарий, чтобы использовать git hash-object -wи git update-index(повторно) вставить зараженный файл непосредственно в индекс. Кто-то очень смелый.
AlexChaffee
11

Я бы предпочел оставить это задание вашему любимому редактору.

Просто установите команду для удаления завершающих пробелов при сохранении.

Giacomo
источник
2
В vim вы можете сделать это с помощью: autocmd BufWritePre .cpp, .c, *. H:% / \ s \ + $ // e
Роберт Массайоли
3
Извините, я проголосовал за комментарий выше, прежде чем его протестировать. После знака процента пропущены буквы "s", и он будет перемещать курсор, если найдены пробелы, и удалит последний шаблон поиска. Смотрите vim.wikia.com/wiki/Remove_unwanted_spaces для лучшей альтернативы.
Сет Джонсон
1
В emacs это Mx delete-trailing-whitespace.
Мовис Ледфорд
2
Более того, для emacs, установите ловушку для удаления конечных пробелов перед сохранением, добавив (add-hook 'before-save-hook 'delete-trailing-whitespace)в свой .emacsфайл. Трюки с пробелами в Emacs
Дункан Паркс
1
Я использую (add-hook 'before-save-hook' whitespace-cleanup), который также преобразует вкладки в пробелы.
Нильс Фагербург
10

Использование атрибутов git и настройка фильтров с помощью git config

Хорошо, это новый подход к решению этой проблемы ... Мой подход состоит в том, чтобы не использовать какие-либо хуки, а использовать фильтры и атрибуты git. Это позволяет вам настроить на каждом компьютере, на котором вы разрабатываете, набор фильтров, которые уберут лишние пробелы и лишние пустые строки в конце файлов перед их фиксацией. Затем настройте файл .gitattributes, в котором указано, к каким типам файлов должен применяться фильтр. Фильтры имеют две фазы, cleanкоторые применяются при добавлении файлов в индекс, иsmudge которые применяются при добавлении их в рабочий каталог.

Скажите вашему git искать глобальный файл атрибутов

Сначала скажите вашей глобальной конфигурации использовать файл глобальных атрибутов:

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

Создать глобальные фильтры

Теперь создайте фильтр:

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

Добавьте магию сценариев sed

Наконец, положить fixup-eol-eof скрипт где-нибудь на вашем пути и сделайте его исполняемым. Сценарий использует sed для редактирования на лету (удаление пробелов и пробелов в конце строк и лишних пустых строк в конце файла)

fixup-eol-eof должен выглядеть так:

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

моя суть этого

Сообщите git, к каким типам файлов применять ваш вновь созданный фильтр

Наконец, создайте или откройте ~ / .gitattributes_global в вашем любимом редакторе и добавьте такие строки, как:

pattern attr1 [attr2 [attr3 […]]]

Поэтому, если мы хотим исправить проблему пробелов, для всех наших исходных файлов c мы добавим строку, которая выглядит следующим образом:

*.c filter=fix-eol-eof

Обсуждение фильтра

Фильтр имеет две фазы: чистая фаза, которая применяется, когда вещи добавляются в индекс или регистрируются, и фаза размазывания, когда git помещает вещи в ваш рабочий каталог. Здесь наше пятно просто запускает содержимое через catкоманду, которая должна оставить их без изменений, за исключением возможного добавления завершающего символа новой строки, если в конце файла его не было. Команда clean - это фильтрация пробелов, которую я собрал из заметок на http://sed.sourceforge.net/sed1line.txt . Кажется, что это должно быть помещено в сценарий оболочки, я не мог понять, как внедрить команду sed, в том числе очистку лишних лишних строк в конце файла непосредственно в файле git-config. (Вы МОЖЕТЕизбавиться от конечных пробелов, однако, без необходимости отдельного сценария sed, просто установите на filter.fix-eol-eofчто-то вроде, sed 's/[ \t]*$//' %fгде \tявляется реальной вкладкой, нажав tab.)

Require = true вызывает ошибку, если что-то идет не так, чтобы вы не попадали в неприятности.

Пожалуйста, прости меня, если мой язык относительно мерзости неточен. Я думаю, что я достаточно хорошо понимаю концепции, но все еще изучаю терминологию.

zbeekman
источник
Интересный подход. +1
VonC
Спасибо @VonC! Я также хочу воспользоваться этой возможностью, чтобы указать, что атрибуты git могут быть настроены для отдельных репозиториев в .gitпапке, а не глобально, что может иметь больше смысла.
zbeekman
9

Я написал этот хук перед фиксацией, который удаляет только пробел из строк, которые вы изменили / добавили, поскольку предыдущие предложения, как правило, создают нечитаемые коммиты, если целевые файлы имеют слишком много пробела.

#!/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
источник
1
Интересный. +1. Смотрите мой другой ответ для вычисления пустого дерева.
VonC
1
Хорошая идея, это именно то, что я хотел бы. Однако будьте осторожны при использовании этого! Для меня на OSX и git версии 2.3.5 он сносит любые дополнения, но незафиксированные изменения, которые я поставил. Я все еще был бы заинтересован в рабочем решении для этого все же.
Каспер
9

Пожалуйста, попробуйте мой предварительный коммит хуки , он может автоматически определить конечный пробел и удалить его . Спасибо!

это может работать под GitBash(windows), Mac OS X and Linux!


Снимок:

$ 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
Интересный. +1. Я сослался на твой хук в своем собственном ответе
VonC
@VonC Спасибо за ваше подтверждение! На «.md», я только нашел git commit -no-verify, какие-нибудь предложения?
старик
Я предпочел бы сделать хук способным обнаруживать .mdфайл, а не удалять пробелы, вместо того, чтобы просить конечного пользователя добавить --no-verifyопцию в git commit.
VonC
Сбой, если зафиксировать файл / каталог, который начинается с +или-
Rody Oldenhuis
6

Вот версия, совместимая с 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

Радоваться, веселиться

sdepold
источник
Похоже, единственное различие между вами и моим заключается в том, что вы проверяете, что sed действительно что-то заменит перед перезаписью файла ... Я не уверен, что это важно, поскольку git не фиксирует изменения, которые на самом деле ничего не меняют. Я полагаю, что это немного безопаснее, но также немного медленнее, и я предпочитаю ясность не повторять регулярные выражения дважды в одной строке. De gustibus non disputandum est!
AlexChaffee
Нет разницы в том, что версия сначала использует синтаксис Ubuntu, а затем (если это не удастся) после OSX.
сдал
1
я отредактировал пост sdepold, теперь он должен иметь возможность разрешать пробелы в именах файлов.
Imme
5

Думал об этом сегодня. Это все, что я сделал для проекта Java:

egrep -rl ' $' --include *.java *  | xargs sed -i 's/\s\+$//g'
Грант Мерфи
источник
3

Для пользователей Sublime Text .

Правильно настройте следующее в настройках пользователя .

"trim_trailing_white_space_on_save": true

Харис Краина
источник
1
Это способ установить это по типу файла? У меня есть *.md(уценка) файлы, которые используют "" (конечные двойные пробелы) для пометки простых <br />, и эта настройка, кажется, применяется ко всем файлам, включая те, которые я не хочу удалять конечные пробелы.
VonC
@VonC Существует иерархия того, как конфигурация применяется. Более подробная информация здесь, stackoverflow.com/questions/16983328/… надеюсь, что это поможет
Харис Краина
2

цикл for для файлов использует переменную оболочки $ IFS. в данном сценарии имена файлов с символом в них, который также находится в переменной $ IFS, будут рассматриваться как два разных файла в цикле for. Этот скрипт исправляет это: модификатор многострочного режима, как указано в sed-manual, по-видимому, не работает по умолчанию на моем компьютере с Ubuntu, поэтому я искал другую реализацию и нашел это с помощью итеративной метки, по сути, он только начнет замену на Последняя строка файла, если я правильно понял.

#!/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] шаблон sed-subition: как заменить символ новой строки (\ n) с помощью sed? ,

оборота immeëmosol
источник
2

Это не удаляет пробелы автоматически перед фиксацией, но это довольно легко сделать. Я поместил следующий скрипт на Perl в файл с именем git-wsf (git whitespace fix) в директорию в $ PATH, чтобы я мог:

мерзавец wsf | ш

и он удаляет все пробелы только из строк файлов, которые git сообщает как 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
источник
0

Немного поздно, но так как это может помочь кому-то там, здесь идет.

Откройте файл в VIM. Чтобы заменить вкладки пробелами, введите в командной строке vim следующую команду

:%s#\t#    #gc

Чтобы избавиться от других конечных пробелов

:%s#\s##gc

Это в значительной степени сделало это для меня. Это утомительно, если у вас есть много файлов для редактирования. Но я обнаружил, что это проще, чем предварительная фиксация и работа с несколькими редакторами.

hriddle
источник
Если это становится утомительным - и если у вас есть резервная копия того, что вы собираетесь редактировать - тогда я часто просто использую sed, чтобы заменить табуляцию на пробелы: sed -i 's|\t| |g' filenames(пробелы в позиции замены). Обратите внимание, что вы можете использовать find, чтобы получить ваши имена файлов. Если вы не задумывались о том, как получить эту резервную копию, я обычно просто фиксирую все и затем «отменяю» фиксацию с программным сбросом обратно туда, где я нахожусь; иногда я добавляю все в дерево, но не фиксирую, а иногда я использую stash / apply (не pop!). Если я испытываю беспокойство, перед тем как вмешаться, я перевожу все свое дерево в безопасное место ...
Мудрец
0

Чтобы удалить конечные пробелы в конце строки в файле, используйте ed:

test -s file &&
   printf '%s\n' H ',g/[[:space:]]*$/s///' 'wq' | ed -s file
натуральный
источник
-1

Это, вероятно, не решит вашу проблему напрямую, но вы можете установить ее с помощью git-config в вашем реальном пространстве проекта, которое редактирует ./.git/config, а не ~ / .gitconfig. Приятно сохранять настройки согласованными среди всех участников проекта.

git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"
Bojo
источник
3
afaik, настройки внутри .git не передаются никому другому; они специфичны для вашего локального репо
AlexChaffee