让git撤销所有仅包含空格的更改?

67

有没有一种简单的方法来自动进行git checkout,以处理只有空格更改的文件?我在处理Windows和从Eclipse运行的代码生成时遇到换行符更改和空格更改,这些更改使我的工作流程充满了噪声,并使跟踪实际更改变得困难。

即使只是一个良好的方式来 报告 哪些文件有真正的更改,哪些没有也是一种开始,而不是必须为每个文件执行diff -w。


这个问题已经得到了回答(请注意,虽然问题只涉及行尾,但回答使用了diff -b,即“忽略空格数量的变化”):https://dev59.com/r2865IYBdhLWcg3wBJ0q - Keilaron
4
可能是如何“git reset”所有仅因行尾差异而不同的文件的重复问题。 - Keilaron
1
相关:Git 仅添加非空格更改 - Joshua Goldberg
7个回答

148

如果您的更改未被暂存

要暂存非空格更改,可以执行以下操作:

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

之后,为了移除所有未暂存的更改(即仅在空格方面有所不同的更改),可以执行以下操作:

git checkout .

如果您的更改已被暂存

通过执行git reset --mixed来取消暂存更改,然后从本回答顶部继续。请注意,mixed是默认模式,可以省略。


1
我从FTP上复制了一堆文件,想看看本地仓库和远程主机之间的差异,但所有文件的行尾都不同,这让识别非空格更改变得非常繁琐。使用以下方法可以很好地识别实际上不同的文件。 - theyetiman
2
起初,这对我没有用,因为我不在存储库的根目录下(尽管我认为不应该要求在根目录下)。所以,如果 git apply 返回成功(0)但没有做任何事情,请尝试进入存储库的根目录。 - Martin R.
1
请注意,如果您设置了 diff.noprefix = true,则上述的 git apply 将会失败。为了解决这个问题,请添加选项 -p0 - void.pointer
5
这为我节省了亿万年的时间…但是在我的情况下有一个警告 - 它不会忽略完全添加/删除的空行。 要包含这一点,请在差异中添加“--ignore-blank-lines”。 - MuertoExcobito
那些懒惰的人不要忘记使用别名,比如: clearws = !git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero - && git checkout . - Maksym Kosenko
显示剩余4条评论

7

这很可能是一个行尾问题;Windows使用CRLF(回车符+换行符,或\r\n)作为行尾,而大多数其他系统则使用LF(换行符,或\n)。幸运的是,Git可以规范化文件,使它们在存储库中始终以LF形式存储,但在Windows上检出时将作为CRLF。您可以通过在Windows上设置core.autocrlftrue来实现此目的:

$ git config --global core.autocrlf true

在Mac和Linux上进行设置,将 core.autocrlf 设置为 input

$ git config --global core.autocrlf input

更多信息可在此处查阅(向下滚动到标题为core.autocrlf的部分)。


1
我知道为什么会这样,我也知道core.autocrlf并将其设置为true。但这些都不能轻松地丢弃由代码生成所做的仅包含空格的更改(例如GraniteDS插件在Windows上甚至也会输出Unix换行符)。 - Sophistifunk
1
@moonlightcheese:他们几年前更改了Git网页,显然有些重定向出现了问题。我已经更新了URL。 - mipadi

7

如果你的更改已经提交

(可能有更聪明的方法,但这对我有效)

mybranch=master
git checkout -b tmp origin/master

# compute the non-ws diff to mybranch and apply it
git diff -U0 -w --no-color $mybranch | git apply -R --cached --ignore-whitespace --unidiff-zero -

git commit -m "non ws changes"
git reset --hard  # discard all non-staged data

您现在位于一个新的“tmp”分支上。您可能需要进行清理(注意:这将丢失$mybranch的历史记录)。

git checkout $mybranch
git reset --hard tmp
git branch -D tmp

使用git commit -C "$mybranch"命令来重用旧的提交信息。 - undefined
此解决方案似乎暗示着masterorigin/master领先一个提交。如果不是这种情况,只需检出master~1即可。应用更改后,只需使用git checkout -B master覆盖master。临时分支也只是可选的。 - undefined

0
另一种方法是在Unix系统上使用dos2unix命令(或者在Windows PC上进行特殊安装),将行尾转换为适合提交和推送的格式。

0

我最终在 Powershell 5.1 中这样做:

# Unstage all pending changes 
git reset

# Create a hashtable to store the files to undo
# By inserting all the files with changes (including whitespace only)
# And then removing the files with real changes 
# Note -w flag indicates to not include whitespace only changes
$files = @{}
git diff --numstat | % { $files.Add($_.Split("`t")[2], $_) }
git diff -w --numstat | % { $files.Remove($_.Split("`t")[2]) }

# Undo the changes
$files.keys | % { git checkout -- $_ }

0

如果您的更改已提交并推送...

...而且您不熟悉高级 git 命令行使用,但可以访问 JetBrains Rider IDE 或 JB 工具系列,通过 GUI 进行混合 git 重置会自动删除空格更改。然后只需提交即可。在 200 多个文件中,它仅错过了一个,我可以手动恢复。

99% 的流程可以通过 GUI 完成。在 Git 标签页中右键单击基础分支,然后进行重置操作。它将撤销提交并为提交阶段非空白字符更改。现在提交和 push -f(我总是通过命令行强制推送)。就这样,您完成了!

enter image description here


-1

rumpel的回答对我来说是正确的解决方法。我只想补充一点:

如果你的更改已经被推送

一旦你按照rumpel的步骤操作,不要再次在你的分支上推送。Github会要求你先拉取,然后你将再次得到每个空格差异。相反,从当前分支创建一个新分支并推送新分支:

# From $mybranch
git checkout -b $mybranch-v2
git push --set-upstream origin $mybranch-v2

然后在 GitHub 上关闭并删除 $mybranch


我不认为有任何理由不强制推送你自己的分支,如果你已经与你的团队讨论过了。 - IC_

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