Я использую git с моей командой и хотел бы удалить переменные пробела из моих различий, журналов, слияний и т.д. Я предполагаю, что самый простой способ сделать это будет для git для автоматического удаления (и другие пробельные ошибки) от всех коммитов, когда они применяются.
Я попытался добавить следующее к файлу ~/.gitconfig
, но при совершении я ничего не делаю. Возможно, он предназначен для чего-то другого. Какое решение?
[core]
whitespace = trailing-space,space-before-tab
[apply]
whitespace = fix
Я использую ruby, если у кого-то есть какие-то рубиновые идеи. Автоматическое форматирование кода перед совершением будет следующим шагом, но это сложная проблема и не вызывает большой проблемы.
Ответ 1
Эти настройки (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
(markdown)!
Ответ 2
Вы можете обмануть Git, чтобы исправить пробелы, обманывая Git, рассматривая ваши изменения как патч. В отличие от решений "pre-commit hook", эти решения добавляют в Git команды исправления пробелов.
Да, это хаки.
Надежные решения
Следующие псевдонимы Git взяты из
мой ~/.gitconfig
.
Под "устойчивым" я имею в виду, что эти псевдонимы работают без ошибок, делая
правильная вещь, независимо от того, являются ли дерево или индекс грязными. Однако они не работают, если интерактивный git rebase -i
уже выполняется; см. my ~/.gitconfig
для дополнительных проверок, если вам небезразличен этот angular случай, где описанный в конце прием 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 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:
# /questions/32680/git-remove-trailing-whitespace-in-new-files-before-commit/238832#238832
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
.
Если мы сделали это вручную:
Установите для apply.whitespace
значение fix
(это нужно сделать только один раз):
git config apply.whitespace fix
Это говорит Git исправлять пробелы в патчах.
Убедите Git рассматривать ваши изменения как патч:
git add -up .
Нажмите a + enter, чтобы выбрать все изменения для каждого файла. Вы получите предупреждение о том, что Git исправляет ваши пробельные ошибки.
(git -c color.ui=auto diff
в этот момент показывает, что ваши неиндексированные изменения являются именно ошибками пробелов).
Удалите ошибки пробелов из вашей рабочей копии:
git checkout .
Верните свои изменения (если вы не готовы их зафиксировать):
git reset
GIT_EDITOR=:
означает использовать :
как редактор и как команду
:
это личность.
Ответ 3
Я нашел 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
Ответ 4
В 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 - выбрать новые шаблоны.
Ответ 5
Я предпочел бы оставить эту задачу в вашем любимом редакторе.
Просто установите команду для удаления конечных пробелов при сохранении.
Ответ 6
Я написал этот крюк pre-commit, который удаляет только оставшееся пробел из строк, которые вы изменили/добавили, поскольку предыдущие предложения, как правило, создают нечитаемые коммиты, если целевые файлы имеют слишком большое количество пробелов в белом пространстве.
#!/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
Ответ 7
Попробуйте мои pre-commit перехватчики, он может автоматически обнаруживать trailing-whitespace и удалить его. Спасибо!
он может работать под 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(-)
Ответ 8
Использование атрибутов 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 приводит к возникновению ошибки, если что-то идет не так, чтобы избежать неприятностей.
Пожалуйста, прости меня, если мой язык относительно мерзости неточен. Я думаю, что я достаточно хорошо понимаю концепции, но все еще изучаю терминологию.
Ответ 9
Вот совместимая версия 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
Удачи
Ответ 10
Думал об этом сегодня. Это все, что я сделал для проекта java:
egrep -rl ' $' --include *.java * | xargs sed -i 's/\s\+$//g'
Ответ 11
for-loop для файлов использует переменную оболочки IFS.
в данном script имена файлов с символом в них, который также находится в переменной IFS, будут рассматриваться как два разных файла в for-loop. Этот script исправляет это:
модификатор многострочного режима, как указано 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 check for whitespace-characters
exec git diff-index --check --cached $against --
[1] sed-subsition pattern: Как заменить новую строку (\n) с помощью sed?.
Ответ 12
Для пользователей Sublime Text.
Правильно установите правильную настройку Конфигурация пользователя.
"trim_trailing_white_space_on_save": true
Ответ 13
Это не удаляет пробелы автоматически перед фиксацией, но это довольно легко осуществить. Я поместил следующий perl script в файл с именем git -wsf (git whitespace fix) в каталоге в переменной $PATH, чтобы я мог:
git 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";
}
Ответ 14
Немного поздно, но так как это может помочь кому-то там, вот так.
Откройте файл в VIM.
Чтобы заменить вкладки пробелами, введите следующую команду в командной строке vim
:%s#\t# #gc
Чтобы избавиться от других отстающих пробелов
:%s#\s##gc
Это в значительной степени сделало это для меня. Это утомительно, если у вас есть много файлов для редактирования. Но мне было легче, чем перехватывать крючки и работать с несколькими редакторами.
Ответ 15
Чтобы удалить конечные пробелы в конце строки в файле переносимо, используйте ed
:
test -s file &&
printf '%s\n' H ',g/[[:space:]]*$/s///' 'wq' | ed -s file
Ответ 16
Это, вероятно, не решит вашу проблему напрямую, но вы можете установить их через git -config в своем фактическом пространстве проекта, который редактирует. /.git/config в отличие от ~/.gitconfig. Приятно поддерживать соответствие параметров всем участникам проекта.
git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"