只添加非空白的变化

我有我的文本编辑器来保存文件时自动修剪尾随的空白,我正在贡献一个OpenSource项目,具有严重的尾随空白问题。

每次我尝试提交一个补丁时,我必须首先忽略所有只有空白的变化,只select相关的信息。 不仅如此,当我运行git rebase我通常会因为这些问题而遇到几个问题。

因此,我希望能够添加仅索引非空白更改,类似于git add -p ,但不必自己select所有更改。

有谁知道如何做到这一点?

编辑:我不能改变项目的方式,他们已经决定,在邮件列表讨论它,忽略这一点。

@Frew解决scheme不是我所需要的,所以这是我为同样的问题所做的别名:

 alias.addnw=!sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero -' 

或者你可以简单地运行:

 git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero - 

更新

根据此评论 ,分别添加了选项-U0--unidiff-zero来解决上下文匹配问题。

基本上它应用补丁应用与add没有空白的变化。 你会注意到,在git addnw your/file仍然是未分离的变化,这是剩下的空白。

– 无颜色不是必需的,但因为我的颜色设置为始终,我必须使用它。 无论如何,比对不起更安全。

这适用于我:

如果你想保持藏身,这是有效的

 git stash && git stash apply && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch 

我不喜欢这些内存,但是我遇到了一个git + cygwin中的一个bug,在这里我失去了一些改变,所以为了确保这些东西进入了reflog,至less我设置了如下内容:

 git add . && git commit -am 'tmp' && git reset HEAD^ && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch 

基本上我们创build一个不包含空间变化的diff,还原所有的变化,然后应用diff。

创build一个只包含实际更改的补丁文件(不包括只有空白更​​改的行),然后清理工作空间并应用该补丁文件:

git diff>备份
git diff -w>更改
git reset –hard
补丁<更改

检查剩余的差异,然后addcommit

Mercurial的等价物是这样做的:

hg diff>备份
hg diff -w>改变
hg恢复 – 所有
hg import – 不提交更改

将以下内容添加到.gitconfig

 anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#" 

感谢@Colin Herbert的灵感答案 。

语法解释

最后的#必须被引用,所以它不会被视为在.gitconfig里面的.gitconfig ,而是被传递,并被当做shell里的注释 – 它被插入在git apply的结尾和用户提供的参数之间该git自动放置在命令行的末尾。 这些参数不是在这里想要的 – 我们不希望git apply来消耗它们,因此前面的注释字符。 你可能想要运行这个命令作为GIT_TRACE=1 git anw来看到这个在行动。

--信号结束的参数,并允许的情况下,你有一个文件名为-w或东西,看起来像一个开关git diff

围绕$@转义的双引号需要保留用户提供的引用参数。 如果"字符没有被转义,它将被.gitconfigparsing器使用,而不能到达shell。

注意: .gitconfig别名parsing不会将单引号识别为任何特殊的字符 – 它唯一的特殊字符是"\\n; (在引号string之外)。 这就是为什么一个"必须永远逃脱,即使它看起来像是在一个单引号string(哪个git是完全不可知的)。

这很重要,例如。 如果你有一个方便的别名在工作树的根目录下执行一个bash命令。 错误的表述是:

 sh = !bash -c '"$@"' - 

正确的是:

 sh = !bash -c '\"$@\"' - 

以下情况如何:

 git add `git diff -w --ignore-submodules |grep "^[+][+][+]" |cut -c7-` 

反引号内部的命令获取非空白变化的文件名称。

顶级答案在所有情况下都不起作用,这是由于补丁上下文中的空白符合注释中的用户。

我修改了命令如下:

 $ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero 

这会生成一个没有上下文的补丁。 应该不是问题,因为补丁是短暂的。

相应的别名,再次修改了其他用户已经提供的内容:

 addw = !sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero' - 

您应该首先考虑是否有意识的尾随空格。 许多项目,包括Linux内核,Mozilla,Drupal和Kerberos(仅仅从维基百科页面的样式中可以看出)都禁止尾随的空格。 从Linux内核文档:

得到一个体面的编辑器,不要留下行尾的空白。

在你的情况下,这个问题是相反的:以前的提交(也可能是当前的提交)没有遵循这个准则。

我敢打赌,没有人真的想要最后的空白,解决这个问题可能是一个可喜的变化。 其他用户也可能遇到同样的问题。 添加尾随空白的贡献者也可能不知道他们正在这样做。

而不是尝试重新configurationgit来忽略问题,或者在编辑器中禁用其他合意的function,我会先在项目邮件列表中发布解释问题的文章。 许多编辑器(和git本身)可以configuration为处理尾随空格。

我发现了一个git pre-commit钩子去除了尾随的空白 。 但是,如果你不能让别人使用它,那么它可能不是一个有效的解决scheme。

  #!/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" done exit