如何使git理解Mac(CR)行尾 [英] How to make git understand Mac (CR) line endings

查看:111
本文介绍了如何使git理解Mac(CR)行尾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于某些原因,我的文件之一包含旧式Mac行尾(在OSX上编辑后).这些是"CR"(回车符)字符,在git diff中显示为^ M.

For some reasons one of my files contains old style Mac line endings (after editing on OSX). These are "CR" (carriage return) characters and show up as ^M in git diff.

Git无法理解它们是行尾代码(真的很难吗?),并将整个文件解释为一行.

Git does not understand that they are line ending codes (really how hard can it be?) and interprets the whole file as a single line.

我知道我可以将文件转换为LF或CRLF结尾,然后再提交回去,但是由于git自动将Windows(CRLF)行结尾转换为LF,因此我希望它将像处理CR行结尾一样好吧.

I know that I can convert the files to LF or CRLF endings and then commit them back, however since git automatically converts my Windows (CRLF) line endings to LF, I was hoping that it would take care of CR line endings as well.

有没有办法让git将CR解释为行尾?

Is there a way to make git interpret CR as a line ending?

推荐答案

TL; DR

创建一个过滤器驱动程序以及.gitattributes:创建一个运行tr '\n' '\r'污迹过滤器和一个运行tr '\r' '\n' clean过滤器,并标记文件( s)正在使用此过滤器.使用仅LF行尾将文件存储在Git中. (筛选器驱动程序在.git/config$HOME/.gitconfig文件中定义,文件的名称或名称模式在.gitattributes中.)

TL;DR

Create a filter driver plus .gitattributes: create a smudge filter that runs tr '\n' '\r' and a clean filter that runs tr '\r' '\n', and mark the file(s) in question as using this filter. Store the file inside Git using LF-only line endings. (The filter driver is defined in a .git/config or $HOME/.gitconfig file and the names or name-patterns for the files go in .gitattributes.)

如您所见,Git强烈喜欢以换行符结尾的行. (它可以与换行符分隔的行一起使用,其中最后一行缺少终止符,但这意味着添加一行会导致对前一个最终行的更改,因为它现在有了换行符终止符,而新的最后一行却丢失了换行符.)这对于单个快照无关紧要,但对于产生有用的差异也很重要.

As you have seen, Git strongly prefers newline-terminated lines. (It can work with newline-separated lines, where the last line is missing the terminator, but this means that adding a line results in a change to the previous final line, since it now has a newline terminator while the new final line is missing the newline terminator.) This does not matter for the individual snapshots, but does matter for producing useful diffs.

现代MacOS像其他所有人一样都使用换行符.仅古老的向后兼容格式具有仅CR的行尾.参见例如此SuperUser Stack Exchange网站发布.

Modern MacOS uses newlines, like everyone else. Only ancient backwards-compatible formats have CR-only line endings. See, e.g., this SuperUser Stack Exchange web site posting.

Git没有内置的 过滤器,无法与此类行尾进行转换.但是,Git 确实具有用于在工作树文件中进行更改的通用机制.

Git does not have a built in filter for converting to or from such line endings. Git does, however, have a general purpose mechanism for making alterations in work-tree files.

请记住,当Git将任何文件存储在快照中时,该文件由Git称为 blob对象表示,该对象存储在内部的特殊,压缩(有时是高度压缩)的Git-唯一的形式.这种形式对Gem来说没有任何用处,因此,对Git来说没有用,因此,当您以有用的形式(例如,通过git checkout)获取文件时,Git会将其扩展为计算机的常规形式.同时,只要您将这样的普通文件转换为仅Git的形式,Git就会将文件压缩为仅Git的形式.每当您使用git add将文件复制回Git的 index 时,就会发生这种情况.

Remember that when Git stores any file in a snapshot, the file is represented by what Git calls a blob object, which is stored internally in a special, compressed (sometimes highly compressed), Git-only form. This form is not useful to anything but Git, so when you get the files in a useful form—via git checkout, for instance—Git expands them into their usual form for your computer. Meanwhile, any time you take a normal file like this and convert it to Git-only form, Git compresses the file down to its Git-only form. That happens whenever you copy a file back into Git's index using git add.

当您放置了工作树时,每个文件的索引副本都会存在,就像提交的副本一样.索引副本采用相同的仅Git格式.此处的主要区别在于,不能更改已提交的副本 ,但是可以更改索引副本 .运行git commit会为此时的索引正确的快照,并为新的提交创建新的快照.因此,索引充当下一次提交的内容.使用git checkout,您将一些现有的提交复制到索引中,然后让Git将其扩展到工作树中.然后使用git add,用更改的工作树文件的压缩版本有选择地替换特定的索引副本.

The index copy of each file exists while you have the work-tree in place, just like the committed copy. The index copy is in the same Git-only format. The key difference here is that the committed copy can't be changed, but the index copy can be changed. Running git commit takes a snapshot of whatever is in the index right at that point, and makes that the new snapshot for the new commit. Hence the index acts as what will go into the next commit. Using git checkout, you copy some existing commit into the index, and have Git expand it into the work-tree; then using git add, you selectively replace particular index copies with compressed versions of the work-tree files that you have changed.

在索引和工作树之间来回复制是进行Windows风格的LF到CRLF转换(反之亦然)的理想点,因此Git就是在这里进行的.如果要执行一些 other 转换,而不是直接将其内置到Git中,则可以在这里告诉Git执行此操作.

This copying, to or from index and work-tree, is the ideal point at which to do Windows-style LF-to-CRLF conversions, or vice versa, so this is where Git does it. If you have some other conversion to perform, not directly built in to Git, this is where you tell Git to do it.

污迹过滤器是Git在将文件从压缩索引副本转换为工作树副本时应用的过滤器.在这里,如果您选择将换行符替换为CRLF Windows样式的行尾或分隔符,则Git会使用一个内部转换器来做到这一点:eol=crlf. clean过滤器是Git在将文件从未压缩的工作树副本转换为压缩的索引副本时应用的过滤器;再次,eol=crlf指示Git进行向后转换.

A smudge filter is one that Git applies when converting a file from compressed index copy to work-tree copy. Here, if you've chosen to have newline characters replaced with CRLF Windows-style line enders-or-separators, Git has an internal converter that will do that: eol=crlf. A clean filter is one that Git applies when converting a file from uncompressed work-tree copy to compressed index copy; here again, eol=crlf directs Git to do the backwards conversion.

如果要用仅CR替换换行符,则必须发明自己的转换器.假设您将整个过程称为convert-cr:

If you want to replace newlines with CR-only, you must invent your own converters. Let's say you call the overall process convert-cr:

*.csv   filter=convert-cr

(而不是*.csv eol=crlf).该行进入.gitattributes(这是一个可提交的文件,应该将其提交).

(instead of *.csv eol=crlf). This line goes into .gitattributes (which is a commit-able file, and you should commit it).

现在,您必须定义convert-cr过滤器.这放在一个Git配置文件中,在这里我们发现了一个小缺陷:该配置文件不可提交.这是一个安全问题:Git将在此处运行任意命令,如果我可以提交此文件并将其克隆,则将运行 I 指定的命令,而没有机会先审查它们.因此,您必须自己将其放入.git/config或全局配置(例如git config --global --edit):

Now you must define the convert-cr filter. This goes in a Git configuration file, and here we find a minor flaw: the configuration file is not commit-able. This is a security issue: Git will run arbitrary commands here, and if I could commit this file and you clone it, you'll run the commands I specify, without getting a chance to vet them first. So you must put this into your .git/config yourself, or into your global configuration (git config --global --edit for instance):

[filter "convert-cr"]
    clean = tr '\r' '\n'
    smudge = tr '\n' '\r'

现在,每当Git将仅Git格式转换时,它将换行符转换为CR,并且每当Git将转换为仅Git格式时,它将转换CR.换行符.

Now whenever Git converts from Git-only format, it will translate the newlines to CRs, and whenever Git converts to Git-only format, it will translate the CRs to newlines.

您今天拥有的任何其中包含\r的现有快照都将以这种方式永久存储. Git永远不会更改任何现有的存储文件!存储的数据是宝贵的并且是非法的.您对此无能为力.嗯,几乎没有什么:您可以完全丢弃那些提交,而可以使用新的和改进的提交.但这很痛苦:每个提交都记住其 parent 提交,因此,如果替换存储库中的早期提交,则必须替换每个子级,孙级等等.他们都记得这个新的提交顺序. (git filter-branch可以完成这项工作.)

Any existing snapshots that you have today that have \r inside them, are stored that way forever. Git will never change any existing stored file! Stored data are precious and inviolate. There is nothing you can do about this. Well, there is almost nothing: you can throw out those commits entirely, making new and improved commits that you use instead. But that's quite painful: every commit remembers its parent commits, so if you replace an early commit in your repository, you must replace every child, grandchild, and so on, so that they all remember this new sequence of commits. (git filter-branch does this job.)

但是,您也可以使用.gitattributes diff驱动程序来指导Git如何在现有提交中 diff 特定文件.有多种方法可以执行此操作,但最简单的方法是定义一个 textconv 属性,该属性将二进制"文件(例如,其存储版本可能仅包含CR字符的文件)转换为文本(面向行,即基于换行符)文件.这里使用的textconv过滤器与污迹过滤器完全相同.

You can, however, instruct Git about how to diff particular files in existing commits, also using .gitattributes and diff drivers. There are multiple ways to do this, but the simplest is to define a textconv attribute, that turns a "binary" file—such as a file whose stored version might have CR-only characters—into a text (line-oriented, i.e., newline-based) file. The textconv filter to use here is precisely the same as the smudge filter.

有关更多详细信息,请参见 gitattributes文档.

For further details, see the gitattributes documentation.

这篇关于如何使git理解Mac(CR)行尾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆