【问题标题】:Remove "no newline at end of file" changes from git stage从 git 阶段删除“文件末尾没有换行符”更改
【发布时间】:2014-10-08 16:28:28
【问题描述】:

我在大型代码库上执行了 sed 搜索/替换,对于 sed 传递的每个文件,如果之前没有文件,它会在末尾添加一个换行符。虽然用 \n 结束最后一行是一个很好的约定,但这是一个巨大的差异,与我试图完成的任务无关。该更改影响了数百个文件,我不想手动检查这些文件并手动git checkout

是否有任何方法可以选择性地添加或删除分段更改,以便忽略“文件末尾没有换行符”的文件?

【问题讨论】:

  • 也许你可以做两次提交:第一次向每个没有的文件添加一个 \n,另一个做你正在用 sed 做的事情;这应该可以一劳永逸地解决问题......
  • @Carpetsmoker - 这会起作用,但首先我必须将受影响的文件分成具有实质性更改的文件和最后只有一个更改的文件以进行两次提交。如果我在做任何其他工作之前接受了您的建议,事情就会变得容易得多。
  • @BenMorris 如果时间不是最重要的,你总是可以在sed 搜索/替换之前回退到提交,并遵循 Carpetsmoker 的建议。 Git 的美妙之处在于,您(几乎)不必告诉自己“我之前应该这样做......”。
  • @Jubobs - 这绝对有帮助。我只能看到带有git diff --ignore-all-space 的重大更改的文件。但是,如果我尝试使用git diff --ignore-all-space --name-only 来获取文件列表以便我可以将它们添加到舞台,由于某种原因,该列表仍然包含只有空格更改的文件。它已经接近了,但还没有完全发挥作用。

标签: git sed newline


【解决方案1】:

从链接的相关问题中,我发现git diff --ignore-all-space 会忽略只有空格更改的文件。 git diff --ignore-all-space --name-only 没有像我预期的那样工作,但确实如此:

git diff --ignore-all-space | grep "+++"

这给了我一个除了空白之外有变化的文件列表,它足够小,我可以手动将它们全部添加到阶段并提交。

感谢大家的cmets,他们非常有帮助。

【讨论】:

  • 我想你在想--ignore-all-space
【解决方案2】:

我所做的与@BenMorris 的解决方案略有不同,后者发现只有 有空格差异且没有其他更改的文件。即使同一文件中有其他有效更改,我也想放弃 EOF 换行更改:

要获取具有此类差异的文件列表:

git diff | grep '\(+++\|No newline at\)' | grep -B 1 'No newline at'

...或者如果您的 grep 支持它,这将清理输出以仅提供路径:

git diff | grep '\(+++\|No newline at\)' | grep -B 1 'No newline at' | grep --perl-regexp -o '\+\+\+ b/\K.*'

只需指出要手动清理哪些文件就足够了,但要自动化其余过程......

如果没有,请下载并安装splitpatch.rb

使用 EOF 换行更改对所有文件中的所有分阶段更改进行完整补丁。 (这包括几个 grep -v 以避免 git 和 splitpatch 输出之间的兼容性小问题。)

git diff --cached | grep '\(+++\|No newline at\)' | grep -B 1 'No newline at' | grep -Po '\+\+\+ b/\K.*' | xargs git  diff --cached   | grep -v "^diff --git a" | grep -v "^index "   > fullpatch.patch

把它分解成大块:

/path/to/splitpatch.rb --hunk fullpatch.patch

这将创建名为 Filename.extention.00#.patch 的单独编号文件,从 000 开始。相反,仅应用每个源文件的最后一个(编号最高的)补丁(下面的行是 bash-only,不是zsh,由于 globbing 的不同):

for f0 in *.000.patch; do (for f_all in ${f0/000/*}; do echo $f_all;  done) | tail -n -1;  done | xargs -n 1 git apply —reverse

使用 EOF 换行符在同一个大块中捕获“真正的”更改并非不可能,因此请查看 git diff 并使用编辑器撤消除最后一行之外的任何更改。

清理:

ls *.patch
rm *.patch

当您将这些小的反向更改添加到索引时,您将丢弃 EOF 处的换行更改。

【讨论】:

    猜你喜欢
    • 2012-01-27
    • 2013-04-28
    • 2019-01-28
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多