我正在和我的团队一起使用git,并希望从我的差异,日志,合并等中删除空格更改。我假设最简单的方法是让git自动删除尾随空格(和来自所有提交的其他空白错误)。
我尝试在~/.gitconfig
文件中添加以下内容,但在提交时它没有执行任何操作。也许它是为不同的东西而设计的。解决方案是什么?
[core]
whitespace = trailing-space,space-before-tab
[apply]
whitespace = fix
我正在使用ruby,以防任何人有任何ruby特定的想法。在提交之前自动进行代码格式化将是下一步,但这是一个难题而不是真正导致大问题。
答案 0 :(得分:103)
这些设置(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
脚本(如this one),不“删除尾随”功能“,但”警告“功能如下:< / p>
if (/\s$/) {
bad_line("trailing whitespace", $_);
}
然而,您可以 build a better pre-commit
hook ,尤其是当您考虑:
在Git中提交只有一些更改添加到暂存区域仍然会导致“原子”修订版可能永远不会作为工作副本存在而且可能无法正常工作。
例如,oldman建议in another answer一个pre-commit
hook来检测并删除空格。
由于该钩子获取每个文件的文件名,我建议小心某些类型的文件:你不想删除.md
(降价)文件中的尾随空格!
答案 1 :(得分:41)
你可以通过欺骗Git将你的变化视为一个补丁来欺骗Git为你修复空白。与&#34; pre-commit hook&#34;相反。解决方案,这些解决方案为Git添加了空格固定命令。
是的,这些都是黑客攻击。
以下Git别名取自
my ~/.gitconfig
强大的&#34;我的意思是这些别名运行没有错误
正确的事情,无论树或索引是否脏。但是,如果互动git rebase -i
已在进行中,它们将无法运作;如果你关心这个角落的情况,请参阅my ~/.gitconfig
以获取更多检查,其中最后描述的git add -e
技巧应该有效。
如果要直接在shell中运行它们,而不创建Git 别名,只需复制并粘贴双引号之间的所有内容即可 (假设你的shell像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
来&#34;编辑&#34;使用身份编辑器:
的补丁:
(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 .
技巧在我从this answer了解git rebase --whitespace=fix
诀窍之前,我到处都在使用更复杂的git add
诀窍。
如果我们手动完成:
将apply.whitespace
设为fix
(您只需执行此操作一次):
git config apply.whitespace fix
这告诉Git修复补丁中的空格。
说服Git将您的更改视为修补程序:
git add -up .
按 a + 输入以选择每个文件的所有更改。您将收到有关Git修复您的空白错误的警告
(git -c color.ui=auto diff
此时显示您的非索引更改正是空白错误。)
从工作副本中删除空格错误:
git checkout .
带回您的更改(如果您还没准备好提交):
git reset
GIT_EDITOR=:
表示使用:
作为编辑器,并作为命令
:
是身份。
答案 2 :(得分:29)
我找到了一个git pre-commit hook that removes trailing whitespace。
#!/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 :(得分: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 - global settings),您可以将其放入$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的主要原因是选择新添加的模板。
答案 4 :(得分:10)
我宁愿把这个任务留给你最喜欢的编辑。
设置命令以在保存时删除尾随空格。
答案 5 :(得分: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
答案 6 :(得分:8)
请尝试my pre-commit hooks,它可以自动检测尾随空格, 将其删除 。谢谢!
它可以在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(-)
答案 7 :(得分:8)
好的,这是解决这个问题的新方法......我的方法是不使用任何钩子,而是使用过滤器和git属性。这允许你做的是,在你开发的每台机器上设置一组过滤器,这些过滤器将在提交之前剥离文件末尾的额外尾随空格和额外空白行。然后设置一个.gitattributes文件,该文件说明应该将过滤器应用于哪些类型的文件。过滤器有两个阶段,在将文件添加到索引时应用了clean,以及在将它们添加到工作目录时应用的涂抹。
首先,告诉您的全局配置使用全局属性文件:
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
最后,将fixup-eol-eof
脚本放在路径上的某个位置,并使其可执行。该脚本使用sed进行一些动态编辑(删除行末尾的空格和空格,以及文件末尾的无关空行)
fixup-eol-eof应如下所示:
#!/bin/bash
sed -e ’s/[ ]*$//‘ -e :a -e '/^\n*$/{$d;N;ba' -e '}' $1
最后,在您喜欢的编辑器中创建或打开〜/ .gitattributes_global并添加以下行:
pattern attr1 [attr2 [attr3 […]]]
因此,如果我们想解决空白问题,对于我们所有的c源文件,我们会添加一行如下所示:
*.c filter=fix-eol-eof
过滤器有两个阶段,即将事物添加到索引或签入时应用的清洁阶段,以及当git将东西放入工作目录时的涂抹阶段。在这里,我们的涂抹只是通过cat
命令运行内容,它应该保持不变,除了可能添加一个尾随换行符(如果文件末尾没有一个)。 clean命令是我从http://sed.sourceforge.net/sed1line.txt的笔记拼凑而成的空白过滤。它似乎必须放入shell脚本,我无法弄清楚如何注入sed命令,包括将文件末尾的无关额外行的卫生直接导入git-config文件。 (你 CAN 摆脱了尾随空白,但是,无需单独的sed脚本,只需将filter.fix-eol-eof
设置为sed 's/[ \t]*$//' %f
\t
所在的位置{{1}}是一个实际的标签,按Tab键。)
如果出现问题,require = true会导致错误,以免让您免于麻烦。
如果我关于git的语言不准确,请原谅我。我想我对这些概念有了很好的把握,但仍在学习术语。
答案 8 :(得分: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
玩得开心
答案 9 :(得分:5)
今天想到这个。这就是我最终为java项目所做的一切:
egrep -rl ' $' --include *.java * | xargs sed -i 's/\s\+$//g'
答案 10 :(得分:2)
for-loop for files使用$ IFS shell变量。 在给定的脚本中,其中包含字符的文件名也位于$ 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-subsition模式:How can I replace a newline (\n) using sed?。
答案 11 :(得分:2)
Sublime Text 用户。
在设置用户配置中正确设置以下内容。
"trim_trailing_white_space_on_save": true
答案 12 :(得分:1)
这不会在提交之前删除自动空格,但它很容易生效。我将以下perl脚本放在$ PATH的目录中名为git-wsf(git whitespace fix)的文件中,以便我可以:
git wsf | SH
并且它会从git报告为差异的文件行中删除所有仅的空格。
#! /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";
}
答案 13 :(得分:0)
稍晚但是因为这可能有助于那里的人,所以这里。
在VIM中打开文件。 要用空格替换制表符,请在vim命令行中键入以下内容
:%s#\t# #gc
摆脱其他尾随空格
:%s#\s##gc
这对我来说非常有用。如果要编辑大量文件,这很乏味。但我发现它比预先提交钩子和使用多个编辑器更容易。
答案 14 :(得分:0)
要以便携方式删除文件末尾的尾随空格,请使用ed
:
test -s file &&
printf '%s\n' H ',g/[[:space:]]*$/s///' 'wq' | ed -s file
答案 15 :(得分:-1)
这可能不会直接解决您的问题,但您可能希望在实际项目空间中通过git-config设置它们,编辑./.git/config而不是〜/ .gitconfig。很高兴保持所有项目成员之间的设置一致。
git config core.whitespace "trailing-space,space-before-tab"
git config apply.whitespace "trailing-space,space-before-tab"