Git是否能够自动切换空格和制表符?

226

我在编写 Python 程序时使用制表符进行缩进,但我想与使用空格缩进的人合作(使用 git)。

是否有一种方法可以让 git 在推送/获取时自动在空格和制表符之间转换(例如,4 个空格 = 1 个制表符),类似于 CR/LF 转换?


43
PEP8恰恰是我的问题。每个人都遵循它,而我却被我的制表符困住了。我碰巧认为一个缩进=一个制表符才是正确的(为什么要用空格?为什么是4个空格?PEP8没有解释...)。无论如何,有了这个git技巧,我可以在我的电脑上愉快地使用制表符,并与所有遵循PEP8规范的人共享我的代码。 - Olivier Verdier
8
哦!我使用TextMate,并且我可以在空格和制表符之间转换。问题是,当我按tab键时,我喜欢我的编辑器写入制表符。所以,如果我用空格检出一个Python项目,我会插入各种制表符。我必须手动转换成制表符,但是当我提交时,它看起来像1000个删除,1000个添加,我的合作者们不会开心的。 :-) - Olivier Verdier
7
PEP8规定使用空格而不是制表符的原因是因为它涉及到连续缩进规则。在括号内部继续过长的行有两种方法。如果您在括号后立即开始新行,则只需缩进一次。如果您将括号的一部分内容放在第一行上,那么您必须在下一行继续括号并且缩进级别与开放括号的缩进级别相同。如果使用制表符,这样做就无法正常工作。 - John Christopher Jones
3
针对这种情况,可以使用制表符来匹配前一行的缩进,然后使用空格来匹配前一行中的位置。这很容易转换为空格。不幸的是,反过来就不成立了,因为它会将缩进信息与对齐信息混合在一起。 - Patrick Parker
4个回答

215

以下是完整的解决方案:

在您的代码库中添加一个名为.git/info/attributes的文件,其中包含:

*.py  filter=tabspace

Linux/Unix

现在运行以下命令:

git config --global filter.tabspace.smudge 'unexpand --tabs=4 --first-only'
git config --global filter.tabspace.clean 'expand --tabs=4 --initial'

OS X

首先使用brew安装coreutils:

brew install coreutils

现在执行以下命令:

git config --global filter.tabspace.smudge 'gunexpand --tabs=4 --first-only'
git config --global filter.tabspace.clean 'gexpand --tabs=4 --initial'

所有系统

现在您可以检查项目的所有文件。您可以使用以下方法完成:

git checkout HEAD -- **

现在所有的Python文件将使用制表符而不是空格。

编辑:更改了强制检出命令。当然,您应该先提交您的工作。


2
@Jeremy:expand/unexpand是Unix命令。你要么得找到Windows的端口/等效物,要么使用类似Cygwin的东西。 - Tim
1
我找到了最好的工作版本 http://sourceforge.net/projects/gnuwin32/files/coreutils/5.3.0/ - hazzik
3
@Marc-André 不错的建议。我实际上使用核心工具版本(安装homebrew,然后运行brew install coreutils)。 - Olivier Verdier
2
似乎这个不再起作用了,过滤器对我没有任何作用。结账后,文件仍然有空格。这方面有任何更新吗? - Philipp Ludwig
2
我发现将属性文件放在~/.config/git/attributes中,配置文件放在~/.gitconfig中会更容易一些,这样这些规则就适用于所有项目,而无需在每个项目中进行操作。 - SurpriseDog
显示剩余9条评论

152

是的,一个潜在的解决方案是使用Git属性过滤器驱动程序(另请参见GitPro书),定义一个smudge/clean机制。

alt text

这样做的好处是:

  • 每次你检出存储库中的一些文件时,空格可以转换为制表符,
  • 但当你提交(并推送和发布)这些相同的文件时,它们将仅使用空格存储回去。

您可以在.git/info/attributes中声明此过滤器驱动程序(此处命名为'tabspace')(适用于Git存储库中的所有文件的过滤器),其内容如下:

*.py  filter=tabspace

现在运行以下命令:

# local config for the current repo
git config filter.tabspace.smudge 'script_to_make_tabs'
git config filter.tabspace.clean 'script_to_make_spaces'

参考Olivier答案,可以得到一个具体的工作示例,来实现这样一组模糊/清洗指令。


1
很不幸,它就是不起作用。我遵循了所有的指示,但是Git没有应用过滤器。:( 当我checkout时,没有应用smudge过滤器,当我checkin时也什么都没发生... Git有时真的很令人沮丧... - Olivier Verdier
@Olivier:奇怪,我从来没有遇到过这样的问题,只要我仔细限制属性过滤器的范围(仅针对特定子树、特定类型的文件),以便不会减慢签出/签入过程。例如,请参见https://dev59.com/JXVD5IYBdhLWcg3wKoaH - VonC
谢谢!现在它可以工作了。请查看完整的解决方案:https://dev59.com/BXE95IYBdhLWcg3watU3#2318063 - Olivier Verdier
@Vonc:也许应该删除“--global”标志,因为这将意味着您将空格发送到每个协作项目... - Willem Van Onsem
只对具有正确.gitattributes的项目使用@CommuSoft。但是,如果将配置保留在存储库本地,则更易于理解。我已经编辑了答案。 - VonC

45

对于使用GitHub(或其他类似服务)的每个人非常有用的信息

~/.gitconfig

[filter "tabspace"]
    smudge = unexpand --tabs=4 --first-only
    clean = expand --tabs=4 --initial
[filter "tabspace2"]
    smudge = unexpand --tabs=2 --first-only
    clean = expand --tabs=2 --initial

那么我有两个文件:

attributes
*.js  filter=tabspace
*.html  filter=tabspace
*.css  filter=tabspace
*.json  filter=tabspace

attributes2

*.js  filter=tabspace2
*.html  filter=tabspace2
*.css  filter=tabspace2
*.json  filter=tabspace2

个人项目开发

mkdir project
cd project
git init
cp ~/path/to/attributes .git/info/

这样,当你最终将你的工作推到github上时,在代码查看器中,它不会因为浏览器都默认使用8个空格缩进而显得很愚蠢。

贡献到其他项目

mkdir project
cd project
git init
cp ~/path/to/attributes2 .git/info/attributes
git remote add origin git@github.com:some/repo.git
git pull origin branch

这样,您就可以在 2 空格缩进 的项目中使用普通标签进行工作。

当然,如果您想要为我的项目做出贡献,并且在开发过程中倾向于使用 2 个空格,可以编写类似的解决方案以将缩进从 4 个空格转换为 2 个空格


3
相关:将git配置存储为仓库的一部分;还要注意您可以在您的仓库中使用(并提交).gitattributes文件。 - Tobias Kienzler
小细节:这与GitHub或任何特定服务无关,只是Git。细节2:您可能希望使用$XDG_CONFIG_HOME/git/config而不是$HOME/.gitconfig来组织配置文件并保持主目录的清洁。 - toastal
但是很有可能你希望将其放在项目文件夹中的.git中,因为项目具有不同的设置并不罕见。 - toastal

1
如果您使用的是Windows操作系统,那么要使@Olivier Verdier's的解决方案生效,需要进行以下几个额外步骤:
  1. 下载CoreUtils for windows
  2. 安装后将安装位置添加到您的PATH变量中(如何添加路径变量
  3. 我将expand.exe重命名为gexpand.exe,因为Windows已经有一个expand实用程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接