求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
 
   
分享到
GitHub 第一坑:换行符自动转换
 
火龙果软件    发布于 2014-05-29
 

源起

一直想在 GitHub 上发布项目、参与项目,但 Git 这货比较难学啊。买了一本《Git 权威指南》,翻了几页,妈呀,那叫一个复杂,又是 Cygwin 又是命令行的,吓得我不敢学了。

终于某天发现 GitHub 还有一个 Windows 客户端,试了一下还挺好用。不需要掌握太多的 Git 原理和命令,也可以在 GitHub 上麻溜建项目了,甚是欢喜。可是好景不长,第一次参与开源项目就出洋相了。

经过

小心翼翼地 Fork 了朴灵大大 (@JacksonTian) 的 EventProxy 项目,本地改好提交,同步到服务器,怀着激动的心情发出 Pull Request……这时发现问题了。我发现 diff 图表显示的更新并不仅是我修改的那几行,而是整个文件都显示为已修改。(下图为示意图)

这看起来很奇怪啊,于是赶紧撤回 Pull Request,自己闷头找原因。

初步定位是文件的换行符问题,因为我发现本地的文件是 Windows 换行符,但很显然大家现在做项目都是用 UNIX 换行符啊。这是一大疑点,于是在反复对比 Web 端和本地的各个文件、各个版本之后,基本定位到了问题所在。

背景

在各操作系统下,文本文件所使用的换行符是不一样的。UNIX/Linux 使用的是0x0A(LF),早期的 Mac OS 使用的是0x0D(CR),后来的 OS X 在更换内核后与 UNIX 保持一致了。但 DOS/Windows 一直使用0x0D0A(CRLF)作为换行符。(不知道 Bill Gates 是怎么想的,双向兼容?)

这种不统一确实对跨平台的文件交换带来麻烦。虽然靠谱的文本编辑器和 IDE 都支持这几种换行符,但文件在保存时总要有一个固定的标准啊,比如跨平台协作的项目源码,到底保存为哪种风格的换行符呢?

Git 作为一个源码版本控制系统,以一种(我看起来)有点越俎代庖、自作聪明的态度,对这个问题提供了一个“解决方案”。

Git 由大名鼎鼎的 Linus 开发,最初只可运行于 *nix 系统,因此推荐只将 UNIX 风格的换行符保存入库。但它也考虑到跨平台协作的场景,并且提供了一个“换行符自动转换”功能。

这个功能默认处于“自动模式”,当你在签出文件时,它试图将 UNIX 换行符(LF)替换为 Windows 的换行符(CRLF);当你在提交文件时,它又试图将 CRLF 替换为 LF。

(看明白了吗?一个版本控制系统会在你不知不觉的情况下修改你的文件。这 TM 简直酷毙了,对吧?)

缺陷

Git 的“换行符自动转换”功能听起来似乎很智能、很贴心,因为它试图一方面保持仓库内文件的一致性(UNIX 风格),一方面又保证本地文件的兼容性(Windows 风格)。但遗憾的是,这个功能是有 bug 的,而且在短期内都不太可能会修正。

问题具体表现在,如果你手头的这个文件是一个包含中文字符的 UTF-8 文件,那么这个“换行符自动转换”功能在提交时是不工作的(但签出时的转换处理没有问题)。我猜测可能这个功能模块在处理中文字符 + CRLF 这对组合时直接崩溃返回了。

这可能还不是唯一的触发场景(毕竟我没有太多精力陪它玩),但光这一个坑就已经足够了。

踩坑

这是一个相当大的坑,Windows 下的中文开发者几乎都会中招。举个例子,你在 Windows 下用默认状态的 Git 签出一个文件,写了一行中文注释(或者这个文件本来就包含中文),然后存盘提交……不经意间,你的文件就被毁掉了。

因为你提交到仓库的文件已经完全变成了 Windows 风格(签出时把 UNIX 风格转成了 Windows 风格但提交时并没有转换),每一行都有修改(参见本文开头的示意图),而这个修改又不可见(大多数 diff 工具很难清楚地显示出换行符),这最终导致谁也看不出你这次提交到底修改了什么。

这还没完。如果其他小伙伴发现了这个问题、又好心地把换行符改了回来,然后你又再次重演上面的悲剧,那么这个文件的编辑历史基本上就成为一个谜团了。

由于老外几乎不可能踩到这个坑,使得这个 bug 一直隐秘地存在着。但在网上随便搜一下,就会发现受害者绝对不止我一个,比如这位大哥的遭遇就要比我惨痛得多。

防范

首先,不要着急去整 Git,先整好自己。你的团队需要确定一个统一的换行符标准(推荐使用 UNIX 风格)。然后,团队的成员们需要分头做好准备工作——配置好自己的代码编辑器和 IDE,达到这两项要求:

在新建文件时默认使用团队统一的换行符标准

在打开文件时保持现有换行符格式不变(不要做自动转换)

这样一方面可以最大程度保证项目代码的规范一致,另一方面,即使现有代码中遗留了一些不规范的情况,也不会因为反复转换而导致混乱。(当然,作为一个强迫症患者,我还是祝愿所有的项目从一开始就步入严谨有序的轨道。)

接下来,我们就可以开始调教 Git 了。我的建议是,完全关掉这个自作聪明的“换行符自动转换”功能。关闭之后,Git 就不会对你的换行符做任何手脚了,你可以完全自主地、可预期地控制自己的换行符风格。

下面主要针对不同的 Git 客户端,分别介绍一下操作方法。

Git for Windows

这货由 Git 官方出品,在安装时就会向你兜售“换行符自动转换”功能,估计大多数人在看完华丽丽的功能介绍之后会毫不犹豫地选择第一项(自动转换)。请千万抵挡住诱惑,选择最后一项(不做任何手脚)。

如果你已经做出了错误的选择,也不需要重新安装,可以直接使用命令行来修改设置。很简单,直接打开这货自带的命令行工具 Git Bash,输入以下命令,再敲回车即可:

git config --global core.autocrlf false

TortoiseGit

很多从 TortoiseSVN 走过来的同学很可能会选用 TortoiseGit 作为主力客户端,那么也需要配置一下。在 Windows 资源管理器窗口中点击右键,选择“TortoiseGit → Settings → Git”,做如下设置。

(由于 TortoiseGit 实际上是基于 Git for Windows 的一个 GUI 外壳,你在上一节所做的设置会影响到上图这些选项的状态,它们可能直接就是你所需要的样子了。)

GitHub 的 Windows 客户端

它是今天的第二被告。这货很容易上手,很适合小白,我主要用它来一键克隆项目到本地。可能正是为了维护简洁易用的亲切形象,这货并没有像 TortoiseGit 那样提供丰富的选项(对“换行符自动转换”这样的细节功能完全讳莫如深啊,我这样的小白死了都不知道怎么死的……)。因此,我们需要手动修改一下它的配置。

GitHub 的 Windows 客户端实际上也是一个壳,它自带了一个便携版的 Git for Windows。这个便携版和你自己安装的 Git for Windows 是相互独立的,不过它们都会使用同一个配置文件(实际上就是当前用户主目录下的.gitconfig文件)。

所以如果你已经配置好了自己安装的 Git for Windows,那就不用操心什么了。但如果你的机器上只装过 GitHub 的 Windows 客户端,那么最简单的配置方法就是手工修改配置文件了。

修改 Git 的全局配置文件

进入当前用户的主目录(通常 XP 的用户目录是C:Documents and Settingsyourname,在 Vista 和 Win7 下是C:Usersyourname),用你最顺手的文本编辑器打开.gitconfig文件。

在[core]区段找到autocrlf,将它的值改为false。如果没找到,就在[core]区段中新增一行:(最终效果见图)

autocrlf = false

事实上上面介绍的所有命令行或图形界面的配置方法,最终效果都是一样的,因为本质上都是在修改这个配置文件。

还有

关掉了 Git 的“换行符自动转换”功能就万事大吉了吗?失去了它的“保护”,你心里会有点不踏实。你可能会问:如果我不小心在文件中混入了几个 Windows 回车该怎么办?这种意外可以防范吗?

事实上 Git 还真能帮你制止这种失误。它提供了一个换行符检查功能(core.safecrlf),可以在提交时检查文件是否混用了不同风格的换行符。这个功能的选项如下:

false- 不做任何检查

warn- 在提交时检查并警告

true- 在提交时检查,如果发现混用则拒绝提交

我建议使用最严格的true选项。

和core.autocrlf一样,你可以通过命令行、图形界面、配置文件三种方法来修改这个选项。具体操作就不赘述了,大家自己举一反三吧。

最后

你可能还会问,如果我的编辑器一不小心把整个文件的换行符都转换成了另一种格式怎么办?还能预防吗?

相关文章

每日构建解决方案
如何制定有效的配置管理流程
配置管理主要活动及实现方法
构建管理入门
相关文档

配置管理流程
配置管理白皮书
CM09_C配置管理标准
使用SVN进行版本控制
相关课程

配置管理实践
配置管理方法、工具与应用
多层次集成配置管理
产品发布管理
 
分享到
 
 
   


软件配置管理的问题、目的
软件配置管理规范
CQWeb 7.1性能测试与调优指南
为什么需要使用ClearCase
ClearCase与RTC的集成
利用ClearQuest 进行测试管理
更多...   


产品发布管理
配置管理方法、实践、工具
多层次集成配置管理
使用CC与CQ进行项目实践
CVS与配置管理
Subversion管理员


配置管理实践(从组织级到项目级)
通号院 配置管理规范与应用
配置管理日构建及持续集成
丹佛斯 ClearCase与配置管理
中国移动 软件配置管理
中国银行 软件配置管理
天津华翼蓝天科技 配置管理与Pvcs