我正在和我的团队一起使用Git,并希望从我的差异、日志、合并等中删除空白更改。我假设做到这一点最简单的方法是Git在应用所有提交时自动删除尾随空白(和其他空白错误)。

我已经尝试将以下内容添加到~/。gitconfig文件,但是当我提交时它什么也不做。也许它是为别的东西设计的。解决方案是什么?

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

我使用Ruby,以防有人对Ruby有任何具体的想法。在提交之前自动格式化代码将是下一步,但这是一个困难的问题,并不是真正造成大问题。


当前回答

我写了这个预提交钩子,它只删除你修改/添加的行中的尾随空格,因为如果目标文件有太多的尾随空格,前面的建议往往会创建不可读的提交。

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

其他回答

我宁愿把这个任务留给你最喜欢的编辑。

只需设置一个命令,在保存时删除尾随空格。

这些设置(核心。空格和apply.whitespace)不是用来移除尾随空格的,而是用来:

核心。空格:检测它们,并引发错误 适用。空格:并删除它们,但只在补丁期间,而不是“总是自动”

我相信git钩子预提交会做得更好(包括删除尾随空格)


注意,在任何给定的时间,你都可以选择不运行pre-commit钩子:

暂时:git提交——no-verify。 CD .git/hooks/;Chmod -x预提交

警告:默认情况下,预提交脚本(就像这个脚本)没有“移除尾随”功能,而是“警告”功能,比如:

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

然而,你可以构建一个更好的预提交钩子,特别是当你考虑到:

在Git中提交时,只向暂存区添加了一些更改,仍然会导致“原子”修订,该修订可能从未作为工作副本存在过,也可能无法工作。


例如,oldman在另一个答案中提出了一个预提交钩子,它可以检测并删除空白。 由于该钩子获取每个文件的文件名,我建议对某些类型的文件要小心:你不希望删除.md (markdown)文件中的尾随空格!


hakre在评论中建议的另一种方法是:

你可以在markdown中在行末有两个空格,而不是在\n前添加“\”作为尾随空格。

然后是内容过滤器驱动程序:

git config --global filter.space-removal-at-eol.clean 'sed -e "s/ \+$//"'
# register in .gitattributes 
*.md filter=space-removal-at-eol

崇高的文本用户。

在“设置-用户”配置中正确设置以下内容。

"trim_trailing_white_space_on_save": true

在macOS(或者可能是任何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 post-commit钩子应用到所有当前和未来的回购中),你可以把它放在$GIT_PREFIX/git-core/templates/hooks中(其中GIT_PREFIX是/usr或/usr/local或/usr/share或/opt/local/share),并在你现有的回购中运行git init。

根据git帮助init:

在现有的存储库中运行git init是安全的。它不会覆盖已经存在的东西。重新运行git init的主要原因是获取新添加的模板。

下面是Ubuntu和Mac OS X兼容的版本:

#!/bin/sh
#

# A Git hook script to find and fix trailing white space
# 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