210

我有一个托管在 github 上的 git 存储库。许多文件最初是在 Windows 上开发的,我不太注意行尾。当我执行初始提交时,我也没有任何 git 配置来强制执行正确的行尾。结果是我的 github 存储库中有许多以 CRLF 行结尾的文件。

我现在在 Linux 上进行部分开发,我想清理行尾。如何确保文件在 github 上使用 LF 正确存储,并在我的工作副本中包含 LF?

我已经建立了一个.gitattributes包含的文件text eol=LF;那是对的吗?有了这个提交和推送,我可以只使用rm我的本地仓库并从 github 重新克隆以获得预期的效果吗?

4

4 回答 4

267

如果没有关于存储库中有哪些文件的信息(纯源代码、图像、可执行文件……),就很难回答这个问题:)

除此之外,我认为您愿意在工作目录中默认使用 LF 作为行尾,因为无论您在 Windows 或 Linux 上工作,您都愿意确保 .git 存储库中的文本文件具有 LF 行尾. 确实比抱歉更安全....

但是,还有一个更好的选择:受益于 Linux 工作目录中的 LF 行结尾、Windows 工作目录中的 CRLF 行结尾和存储库中的 LF 行结尾。

由于您部分地在 Linux 和 Windows 上工作,请确保core.eol设置为nativecore.autocrlf设置为true.

然后,将.gitattributes文件的内容替换为以下内容

* text=auto

这将让 Git 在提交和签出时为您处理自动换行符。二进制文件不会被更改,检测为文本文件的文件将看到动态转换的行尾。

但是,由于您知道存储库的内容,您可以帮助 Git 帮助他从二进制文件中检测文本文件。

如果您从事基于 C 的图像处理项目,请将.gitattributes文件内容替换为以下内容

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

这将确保扩展名为 c、h 或 txt 的文件将以 LF 行结尾存储在您的存储库中,并且在工作目录中将具有本机行结尾。Jpeg 文件不会被触及。所有其他人都将受益于与上述相同的自动过滤。

为了更深入地了解这一切的内部细节,我建议你深入阅读 Githubber 的 Tim Clem 的这篇非常好的文章“Mind the end of your line”

作为一个真实世界的示例,您还可以查看此提交.gitattributes,其中演示了对文件的这些更改。

更新考虑到以下评论的答案

我实际上不想在我的 Windows 目录中使用 CRLF,因为我的 Linux 环境实际上是一个共享 Windows 目录的 VirtualBox

说得通。感谢您的澄清。在这种特定情况下,.gitattributes文件本身是不够的。

对您的存储库运行以下命令

$ git config core.eol lf
$ git config core.autocrlf input

由于您的存储库在 Linux 和 Windows 环境之间共享,这将更新这两个环境的本地配置文件。core.eol将确保文本文件在结帐时带有 LF 行结尾。core.autocrlf将确保文本文件中的潜在CRLF(例如,由复制/粘贴操作产生)将在您的存储库中转换为 LF。

或者,您可以通过创建包含类似于以下内容的文件来帮助 Git 区分什么是文本文件:.gitattributes

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

如果您决定创建一个.gitattributes文件,请提交它

最后,确保git status提及“nothing to commit (working directory clean)”,然后执行以下操作

$ git checkout-index --force --all

这将在您的工作目录中重新创建您的文件,同时考虑您的配置更改和.gitattributes文件,并替换文本文件中任何可能被忽略的 CRLF。

完成此操作后,工作目录中的每个文本文件都将以 LF 行结尾,并且git status仍应将 workdir 视为干净。

于 2012-04-02T14:05:26.470 回答
198

从 Git 2.10(2016-09-03 发布)开始,无需单独枚举每个文本文件。Git 2.10修复了text=autowitheol=lf的行为。来源

.gitattributesGit 存储库根目录中的文件:

* text=auto eol=lf

添加并提交。

之后,您可以执行以下两个步骤来规范化所有文件:

git rm --cached -r .  # Remove every file from git's index.
git reset --hard      # Rewrite git's index to pick up all the new line endings.

资料来源:kenorb 的回答

于 2017-02-09T11:47:23.597 回答
27

要强制所有文本文件以 LF 行结尾,您可以.gitattributes使用以下行在存储库的顶层创建文件(根据需要更改):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

这确保了 Git 认为是文本文件的所有文件LF在存储库中都有规范化的 ( ) 行结尾(通常core.eol配置控制默认情况下你有哪一个)。

基于新的属性设置,任何包含 CRLF 的文本文件都应该被 Git 规范化。如果这不会自动发生,您可以在更改行尾后手动刷新存储库,以便您可以通过以下步骤重新扫描并提交工作目录(给定干净的工作目录):

$ echo "* text=auto" >> .gitattributes
$ rm .git/index     # Remove the index to force Git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"

或根据GitHub 文档

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git's index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

另请参阅:@Charles Bailey 帖子

此外,如果您想排除任何不被视为文本的文件,请取消设置其文本属性,例如

manual.pdf      -text

或将其显式标记为二进制:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

要查看一些更高级的 git 规范化文件,请查看.gitattributesDrupal核心

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

也可以看看:

于 2016-01-15T11:37:19.230 回答
1

我正在将 Chromium 克隆depot_tools到我的 mac,工作副本的所有文件都以 CRLF 结尾。我发现这个脚本解决了我的问题。

cd <your repo>
# config the local repo to use LF
git config core.eol lf
git config core.autocrlf input

# Copy files from the index to the working tree
git checkout-index --force --all

# If above line doesn't work, delete all cached files and reset.
git rm --cached -r .
git reset --hard
于 2022-02-19T05:03:44.097 回答