如何使用git撤销所有的空格更改

47

我有一个Git仓库,在本地替换了许多文件。

现在,git status显示很多已修改的文件。

其中一些是“真正修改过的”,另一些只有行尾不同。

我想让那些只有行尾不同的文件消失(使用 git reset ),但我似乎找不到能够实现它的Linux管道命令。

如果能告诉我如何删除唯一不同之处是可执行位的文件,则额外奖励分数。


1
快速提示:你最终会在所有这些文件上运行 git checkout,而不是 git reset - Cascabel
4个回答

50
这样做就可以了:
  git diff -b --numstat \
| egrep $'^0\t0\t' \
| cut -d$'\t' -f3- \
| xargs git checkout HEAD --
  1. 运行工作副本与索引的差异,并为每个文件提供机器可读的摘要,忽略空格变化。
  2. 查找根据 diff -b 没有更改的文件。
  3. 获取它们的名称。
  4. 将它们传递给分支尖端的 git checkout 命令。

如果您省略某些步骤,此管道将对每个步骤执行合理操作,因此您可以从第一行开始并添加更多内容以查看每个步骤发生的情况。

可能有用的替代最后一行:

| git checkout-index --stdin

这将使文件重置为它们的暂存内容,而不是它们的最后提交状态。
你可能还想在第一行使用git diff HEAD,以获取工作副本与最后一次提交之间的差异,而不是与索引之间的差异。
注意:如果您的文件名中有空格,则首先需要添加一个tr
  git diff -b --numstat \
| egrep $'^0\t0\t' \
| cut -d$'\t' -f3- \
<b>| tr '\n' '\0' \</b>

那么您必须在您想要使用的最终命令中添加-0/-z开关:

| xargs <b>-0</b> git checkout HEAD --
# or
| git checkout-index --stdin <b>-z</b>

对于包含空格的文件名,这会失败并显示以下错误信息:error: pathspec '...' did not match any file(s) known to git.我在管道中添加了 sed 命令来引用文件名:git diff -b --numstat | egrep $'^0\t0\t' | cut -d$'\t' -f3- | sed -E 's/(.+)/"\1"/' | xargs git checkout HEAD -- - thenickdude
@thenickdude:有一种更好的方法,可以使用NUL终止符,而不是引号。我已经更新了我的回答。 - Aristotle Pagaltzis

17

虽然看起来你最初在寻找基于管道的解决方案,并从@aristotle-pagaltzis那里得到了,但由于有点难记,我认为这个替代方案值得注意:

git diff -b > gitdiffb
git stash  # or git reset --hard if you feel confident
git apply --ignore-space-change gitdiffb

如果不仅要忽略空白数字的变化,还要忽略全新或完全删除的空格,那么将-b替换为-w

与基于管道的解决方案相比,其结果在删除包含相关更改的文件中的空格变化时有所不同。 因此,它并不完全符合您描述的方式,但对于大多数通过搜索引擎进入此处的人,可能更希望看到这种方法。


1
这个可以在Windows下运行,不需要任何额外的工具。谢谢! - Sonata
3
这是更好的答案:没有黑暗魔法,也没有额外的工具,适用于任何平台。 - marcotama

3

1

如果你对bash过敏,更喜欢powershell(为了清晰起见格式)...

git diff  --numstat --ignore-space-change --ignore-all-space 
          --ignore-blank-lines --ignore-cr-at-eol 
          --ignore-space-at-eol 
| % {($added,$deleted,$path)= $_.Split("`t"); 
    if ("$added$deleted" -eq "00") {$path} 
| % { git checkout HEAD $_}

请注意,这是一种相当激进的方法 - 我在这里使用的git选项也将忽略添加/删除的空行。同时,请记住,空格甚至换行符在字符串中间时可能具有语义意义,因此请谨慎使用。
可能有些git选项是多余的,但出于谨慎起见,我已经包含了它们。您可以查阅文档以形成自己的解释。
这里是一个更简洁的实现供剪切和粘贴...
git diff --numstat -b -w --ignore-blank-lines --ignore-cr-at-eol --ignore-space-at-eol | % {($a,$d,$p)= $_.Split("`t");if ("$a$d" -eq "00") {$p}| % { git checkout HEAD -- $_}

如其他地方所述,建议在还原之前通过运行git stash或首先复制到备份文件夹来保存更改的副本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接