我有一个现成的代码库,其中行尾标识已经混乱了。我想重新编写整个代码库,并一劳永逸地解决行尾标识问题。假设 Git 检测二进制文件的启发式算法能够正常工作,那么如何最简单地用规范化的行尾标识重新填充整个代码库呢?
自Git 2.16(2018年第一季度)以来,有另一种方法(而不是删除索引内容),这是一种新的、更安全的记录您正在更正行尾约定的方式:
git add --renormalize .
请参见提交 9472935(2017年11月16日),由Torsten Bögershausen (tboegi
)提交。
(由Junio C Hamano -- gitster
--于提交 af6e0fe中合并,2017年11月27日)
add
: 引入 "--renormalize
"
Make it safer to normalize the line endings in a repository.
Files that had been committed with CRLF will be committed with LF.The old way to normalize a repo was like this:
# Make sure that there are not untracked files $ echo "* text=auto" >.gitattributes $ git read-tree --empty $ git add . $ git commit -m "Introduce end-of-line normalization"
The user must make sure that there are no untracked files, otherwise they would have been added and tracked from now on.
The new "add --renormalize" does not add untracked files:
$ echo "* text=auto" >.gitattributes $ git add --renormalize . $ git commit -m "Introduce end-of-line normalization"
Note that "
git add --renormalize <pathspec>
" is the short form for "git add -u --renormalize <pathspec>
".
注意:Git 2.21(2019年2月)修复了与此相关的错误:“git add --ignore-errors
”未按照广告宣传的方式工作,而是作为“git add --renormalize
”的意外同义词工作,已经得到修复。
请参见提交记录9e5da3d(2019年1月17日),作者为Jeff King(peff
)。
(由Junio C Hamano -- gitster
--于提交记录1c41824中合并,2019年2月5日)
提交 9472935(
add
:使用单独的ADD_CACHE_RENORMALIZE标志
add
:引入“--renormalize
”,2017年11月16日,Git 2.16)教给git add
将HASH_RENORMALIZE
传递给add_to_index()
,然后将该标志传递给index_path()
。add_to_index()
和index_path()
所采取的标志是不同的命名空间。add_to_index()
中采用HASH_*
标志,因为它们与我们已经采用的ADD_CACHE_*
标志重叠(在这种情况下,HASH_RENORMALIZE
与ADD_CACHE_IGNORE_ERRORS
冲突)。
我们可以通过添加新的ADD_CACHE_RENORMALIZE
标志来解决这个问题,并在add_to_index()
中使用它来设置HASH_RENORMALIZE
。
为了清楚地表明这两个标志来自不同的集合,让我们还将函数中的名称“newflags
”更改为“hash_flags
”。
另外: 请参见 提交记录 e2c2a37 (2019年2月7日),作者为Jeff King (peff
)。
(合并者为Junio C Hamano -- gitster
,已合并至提交记录 9293bf6,2019年2月7日)
提交9e5da3d(
add_to_index()
: 将遗忘的HASH_RENORMALIZE
检查进行转换
add
: 使用单独的ADD_CACHE_RENORMALIZE
标志,2019-01-17)切换我们在标志字段中使用HASH_RENORMALIZE
为新的ADD_CACHE_RENORMALIZE
标志。HASH_RENORMALIZE
检查转换为新标志,这完全破坏了"git add --renormalize
"。
Git 2.37.3 (2022年第三季度), "git add --renormalize
"(手册) 澄清了一个边角情况
请查看efaec7ce提交(2022年8月10日),作者为Philip Oakley (PhilipOakley
)。
(由Junio C Hamano -- gitster
--在58ded4a提交中合并,2022年8月18日)
doc add
: renormalize is not idempotent for CRCRLF签署者:Philip Oakley
评论者:Torsten Bögershausen
/r/r/n
的文件需要进行两次规范化。add
: introduce, 2017-11-16, Git v2.16.0-rc0 -- merge listed in batch #6)(add: introduce "--renormalize
", Torsten Bögershausen, 2017-11-16)。
git add
现在在其手册页面中包含以下内容:
此选项意味着
-u
。
孤立的CR字符不受影响,因此虽然CRLF会被清理为LF,但CRCRLF序列仅部分地清理为CRLF。
* -text
,然后删除并重新添加文件,以最终正确的行尾结束,这些行尾不应该被git修改。 - JustAMartingit add --renormalize
不应该避免删除/添加步骤吗? - VonCrenormalize
应该在新的 git 版本中也适用于“denornalization”(将 git stage 更新为当前工作副本中的文件 EOLs),但我还没有机会尝试它 - 下次会记住的。 - JustAMartin如果您只想在设置了 core.autocrlf
或 text=auto
后重新规范化当前提交,以便您可以在一个提交中进行所有的行结尾规范化,请运行以下命令:
git rm --cached -rf .
git add .
如果您也想规范化工作目录中的文件,请运行:
git checkout .
这可以不用 git 来使用。 然后,稍后 git commit
代码库。
for f in $(find ./ -type f ) ; do
if grep -qP '\x00' $f ; then
# file is binary
continue
fi
perl -pe 'BEGIN{ undef $/} s/\x0d\x0a/\x0a/g;s/\x0d/\x0a/g' -i $f
done
grep 假设任何包含空字符的内容都是二进制文件。
perl 用于原地编辑每个文件。首先,将 Windows 样式的换行符更改为 Unix 样式的换行符。然后将 Mac 样式的换行符更改为 Unix 样式的换行符。
nocr
的简单脚本,几乎和你的一模一样,只是使用了tr而不是perl。它存在于我的路径中,我经常使用它。你的“这是一个二进制文件吗”的测试是一个很好的想法。@wovano:你说得对,这是危险的,但实际上没有一种不危险的方法来做这个。最终,为了安全起见,你将不得不以某种方式手动指定要处理的文件。也许可以添加一个子句,明确排除以.o,.a,.so,.dat,.bin结尾的任何文件,或者相反,限制为.c,.cpp,.java等文件。 - undefined.gitattributes
文件(该文件在2011年还不存在,但自2018年起可用)是正确且安全的方法来解决这个问题。如果git
已经实现了这个功能,就没有必要编写自定义脚本。另外,请注意这样的脚本需要定期运行,而.gitattributes
解决方案可以一劳永逸地解决OP所要求的问题 :) - undefined.gitattributes
并在适用的地方使用它。我之所以提到我的nocr
脚本,是因为它在git之外也有用途。但你说得对,如果你想修复git仓库中的换行符问题,那么这里列出的其他方法更好。 - undefined
git add --renormalize .
:请参见下面的我的答案。 - VonCgit push -f
来传播你的更改,然后该仓库的任何子仓库都需要执行新的git pull
。其次,这将对任何尝试跨越你进行更改的提交的git diff
造成困扰,除非使用-w
参数。 - undefined