仅添加非空白更改

Edu*_*ipe 325 git whitespace

我有我的文本编辑器在保存文件时自动修剪尾随空格,我正在为一个开源项目做出贡献,该项目在跟踪空白时存在严重问题.

每次我尝试提交补丁时,我必须首先忽略所有仅限空白的更改,以便仅选择相关信息.不仅如此,但是当我跑步时,git rebase我经常因为它们而遇到几个问题.

因此,我希望能够以类似的方式添加索引非空白更改git add -p,但不必自己选择所有更改.

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

编辑:我不能改变项目的工作方式,他们在邮件列表上讨论之后决定忽略这一点.

Col*_*ert 376

@Frew解决方案不是我需要的,所以这是我为完全相同的问题所做的别名:

alias.addnw=!sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero -'
Run Code Online (Sandbox Code Playgroud)

或者你可以简单地运行:

git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -
Run Code Online (Sandbox Code Playgroud)

更新

根据此评论,添加了选项-U0,以及--unidiff-zero解决方法上下文匹配问题.

基本上它应用了将在add没有空格更改的情况下应用的补丁.您会注意到,在git addnw your/file仍然存在未分级的更改之后,它就是剩下的空白.

--no-color不是必需的,但由于我总是设置颜色,我必须使用它.无论如何,比抱歉更安全.

  • 应该有一个git add选项,比如`git add -w`这样做. (96认同)
  • 不适合我.得到了'补丁不适用'的错误. (16认同)
  • 如果由于@bronson指出的上下文空格而导致'补丁失败',这个修改后的命令可以工作(它生成一个没有上下文的补丁):`git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero`.这没有风险,因为索引已经是最新的,因此它是补丁的可靠基础. (10认同)
  • 这对我很有用,但是我不得不使用``git apply --ignore-whitespace``,否则补丁不适用于显而易见的原因. (7认同)
  • 这给我带来了'补丁不适用'和'搜索时出错'的问题......任何想法? (6认同)
  • **这个**的两个问题:1)这将添加*所有*跟踪文件,忽略任何用户指定的文件/目录.2)带有空格或`; rm -rf --no-preserve-root /;`的文件名将导致问题.3)创建了不必要的子shell.有关解决方案,请参阅[我的回答](http://stackoverflow.com/a/39487648/5353461). (3认同)
  • 我使用 bash 别名而不是 [git 别名](http://git-scm.com/book/en/v2/Git-Basics-Git-Aliases)。这是我添加到 ~/.bashrc 的内容: `alias gadw='sh -c '\''git diff -w --no-color "$@" | git apply --cached --ignore-whitespace'\'' - '` (2认同)
  • 这似乎只适用于存储库根目录 (2认同)
  • 此命令在 repo 中添加 *all* 文件。要指定您需要添加哪些文件:`git diff -U0 -w --no-color -- PATH\TO\FILE.HERE | git apply --cached --ignore-whitespace --unidiff-zero -`。 (2认同)

Fre*_*idt 36

这对我有用:

如果你想保留一个存储,这是有效的

git stash && git stash apply && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch
Run Code Online (Sandbox Code Playgroud)

我不喜欢的藏匿处,但我已经运行到混帐+ cygwin的,我失去了变化的缺陷,所以要确保这些东西去了,至少我设置以下的引用日志:

git add . && git commit -am 'tmp' && git reset HEAD^ && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch
Run Code Online (Sandbox Code Playgroud)

基本上我们创建一个不包含空间变化的差异,还原我们所有的变化,然后应用差异.

  • 我同意科林的观点.如果脚本有效,那么就不需要创建存储.可能会考虑的好处是运行stash,然后存储pop.如果有必要,可以恢复弹出的藏匿处,但是否则你不会留下很多的藏匿处.这也留下了额外的文件 (3认同)

Ste*_*ers 30

创建仅包含实际更改的修补程序文件(不包括仅包含空格更改的行),然后清理工作区并应用该修补程序文件:

git diff> backup
git diff -w>更改
git reset - 硬
补丁<更改

然后addcommit正常情况一样,检查剩余的差异.

Mercurial的等价物是这样做:

hg diff> backup
hg diff -w>更改
hg revert --all
hg import --no-commit changes

  • 这实际上是我见过的最干净,最容易理解,最不易破碎的方法. (7认同)
  • @jww原始海报的核心问题是"如何避免仅对白色空间进行源代码控制的更改".OP恰好使用Git,但这也适用于我曾经使用的每个源控制系统.如果有人碰巧使用Mercurial,这个答案会显示正确的程序.我可以想象其他人也可能为使用Sublesion等的人们提供解决方案. (4认同)
  • @jww 和 @ pagid:我编辑了我的答案以专门解决 Git,使用与我的 Mercurial 解决方案相同的方法。在我看来,StackOverflow [不仅仅是另一个 Q+A 论坛](http://meta.stackexchange.com/questions/92107/is-stack-overflow-a-forum) - 它还具有存储库的作用的知识。原发帖者以外的人可能会从所给出的答案中受益,并且他们的情况各不相同。这就是为什么我相信传达一般原则的答案是有效的,而不是只针对单一的具体情况。 (4认同)

voi*_*ter 10

由于评论中的用户根据补丁上下文中的空白,所以在所有情况下,最高投票的答案都不起作用.

我按如下方式修改了命令:

$ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero
Run Code Online (Sandbox Code Playgroud)

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

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

addw = !sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero' -
Run Code Online (Sandbox Code Playgroud)


Tom*_*ale 10

将以下内容添加到您的.gitconfig:

anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"
Run Code Online (Sandbox Code Playgroud)

感谢@Colin Herbert对灵感的回答.

语法说明

最终#必须引用,所以它不被视为内部的注释.gitconfig,而是被传递并被视为shell中的注释 - 它被插入git apply到用户提供的参数的末尾和git自动放置在命令行的结尾.这里不需要这些参数 - 我们不想git apply使用它们,因此前面的注释字符.您可能希望运行此命令GIT_TRACE=1 git anw以查看此操作.

--参数的信号结束,并允许您有一个名为-w或看起来像切换到的文件的情况git diff.

需要使用转义的双引号$@来保留任何用户提供的引用参数.如果"角色没有被转义,它将被.gitconfig解析器使用而不会到达shell.

注:.gitconfig别名解析不承认单引号的任何特殊-它的唯一的特殊字符",\,\n,和;(一个外"-quoted字符串).这就是"必须总是被转义的原因,即使它看起来像是在一个单引号字符串中(git完全不可知).

这很重要,例如.如果你有一个方便的别名来bash在工作树的根目录中执行命令.不正确的表述是:

sh = !bash -c '"$@"' -
Run Code Online (Sandbox Code Playgroud)

虽然正确的是:

sh = !bash -c '\"$@\"' -
Run Code Online (Sandbox Code Playgroud)


kar*_*aze 6

以下内容如何:

git add `git diff -w --ignore-submodules |grep "^[+][+][+]" |cut -c7-`
Run Code Online (Sandbox Code Playgroud)

反引号内的命令获取具有非空白更改的文件的名称.

  • 或者只是`git add \`git diff -w | grep'^ +++'| cut -c7- \``如果没有使用子模块 (2认同)