【问题标题】:Git convert between tabs and spaces but only sometimesGit 在制表符和空格之间转换,但只是有时
【发布时间】:2017-06-27 00:41:26
【问题描述】:

首先,我是 git 的新手。就像,如果它在暂存区击中我,我几乎无法从索引中分辨出缓存。或类似的东西。有了这个,我的问题是:

假设我想从事一个项目,其编码风格要求使用空格进行缩进,但我喜欢制表符。似乎我可以使用清洁和涂抹功能,但有一个问题。编码风格并不一致,有些文件在同一行混合了制表符和空格。因此,一种天真的方法会导致我进行单行更改,但意外地创建了一个大规模提交,这使项目完全符合其自己的标准。这会很好,只是差异会不那么有用,所以我最终会遇到新的敌人。

所以问题是:有没有办法让这种魔法发挥作用,如果我不触摸文件,它就不会出现在图片之外? (即使我只更改了一个字符,我也愿意对我接触的文件的空白承担全部责任。)

编辑:好的,我刚刚接受了昨天接受的答案。我很确定这对我很粗鲁。我的借口是我今天才开始测试它。由于显然已经有两个人误解了我,让我弄清楚我实际上做了什么,所以也许有人可以告诉我我是否感到困惑和/或困惑。

$ ls -a
.  ..  t.txt
$ hd t.txt # file contains 3 bytes: a tab, a capital A, and a newline
00000000  09 41 0a                                          |.A.|
00000003
$ git init
Initialized empty Git repository in /home/marvy/test/.git/
$ git config --local git config --local user.name me
$ git config --local user.email me@example.com
$ git add t.txt
$ git commit
[master (root-commit) 959bf99] testing cleverness of git status
 1 file changed, 1 insertion(+)
 create mode 100644 t.txt
$ echo '*.txt filter=tabspace' > .git/info/attributes
$ cat .git/info/attributes
*.txt filter=tabspace
$ git config --local filter.tabspace.smudge unexpand
$ git config --local filter.tabspace.clean expand
$ rm t.txt
$ git checkout t.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   t.txt

no changes added to commit (use "git add" and/or "git commit -a")
$ git help --stackoverflow

正如我们在这里看到的,git status 报告 t.txt 已被修改,即使我刚刚检查了它。如果你运行 git diff,它会声称我想将制表符转换为空格。我做错了吗?

【问题讨论】:

  • 没有回答你的问题,但我很好奇你为什么要这么麻烦。当编辑器相当愚蠢的时候,我也非常喜欢制表符而不是空格。但是由于 IDE 编辑器的语法意识越来越强,我很难区分它们。您使用什么编辑器来编辑标签实际上更容易?
  • 在你最喜欢的编辑器中试试这个。将光标定位在一行的“开头”;即第一个非空白字符。现在按键盘上的左箭头键。会发生什么?
  • 好的。我很少或从不需要这样做。
  • 真的吗?我可能会在任何给定的时间内多次这样做,如果它真的正常工作,我会做得更多。我想每个人都不一样:)

标签: git whitespace


【解决方案1】:

您可以使用预提交挂钩,仅循环浏览您编辑的文件并将制表符替换为空格。类似于以下内容:

FILES=`git status -s -uno | egrep '^M' | sed 's/^M//'`

for FILE in $FILES
do
    (sed -i 's/[[:space:]]*$//' "$FILE" > /dev/null 2>&1 || sed -i '' -E 's/[[:space:]]*$//' "$FILE")
fi

【讨论】:

  • 这真的有效吗? “git status”是否足够聪明地意识到文件没有改变,即使它们在磁盘和 repo 中看起来不同?如果是这样,这是否意味着带有涂抹和清洁的原始“幼稚”解决方案也有效? (另外:我在 Windows 上,没有 sed 适合我。虽然想起来我确实安装了 Cygwin。嗯......)
  • @MarkVY “git status”是否足够聪明,可以意识到文件没有改变,即使它们在磁盘和 repo 中看起来不同?是的。是的,涂抹和清洁工作,并作为 bash 脚本执行,即使在 Windows 上也是如此。是的,你已经在你的 CMD 会话中使用了 sed 和 200 多个其他 unix 命令(不需要 bash 或 cygwin):你只需要从你的 Git 安装中添加 usr/bin,就像在stackoverflow.com/a/44510644/6309 中一样。
  • 好的,这很可爱!谢谢!
【解决方案2】:

最好的方法是使用带有smudge-clean 的脚本。

smudge-clean

Smudge/Clean 是过滤器,它在文件通过舞台区域的任何地方运行,这些过滤器将通过执行给定脚本来修改文件。

使用 smudge 和 clean 只会触及您通过暂存区的文件。


例如(unix 示例): 如果您不熟悉uexpand/unuexpand,请阅读它 here

~/.gitconfig

# filters to convert between tabs to spaces
[filter "tabspace"]
    smudge = unexpand --tabs=2 --first-only
    clean = expand --tabs=2 --initial

~/.git 属性

*.txt  filter=tabspace

现在,无论何时添加/签出文件,它们都会根据您的配置进行转换。

你也可以看看这个project in github

【讨论】:

  • 看来我的不清楚是无可救药的,因为每个人都在试图回答一个我没有问过的问题。您提倡的设置会导致 git status 声称我修改了我从未接触过的文件,因为这些文件不符合官方项目编码风格,过滤器会尝试使它们符合。我的问题的重点是如何避免这种情况!我知道我说我是一个 git 新手,但这并不意味着我如此无助以至于我无法阅读文档。在这里给我一点信任:)
  • 享受你的自动赏金吧 :) 我仍然不接受答案。这是一个很好的答案,只是不是我的问题:)
【解决方案3】:

设置存储库:

  1. 获取存储库。
  2. 合并到本地主分支。

做出重大改变:

  1. 您可以根据需要更改整个存储库。做任何你想做的和你需要做的。做出改变一切的那一行。但只将您自己接触过的文件添加到“暂存区”。换句话说,您必须手动添加这些文件:git add FilesYouWantToAdd.txt 以及您负责的任何其他文件。不要将您不负责的文件添加到暂存区。

    git commit -m 'alter spaces to tabs' // 只添加你负责的文件。

    git 推送

你就完成了。

放弃其他更改:

因为其余文件中没有任何实质性更改,您可以简单地放弃这些更改。

git reset HEAD .

其实很简单。希望这会有所帮助。

编辑:

【讨论】:

  • 换句话说,“git status”在识别我没有改变的地方是没有用的,对吧?
  • @MarkVY 如果对文件进行了任何更改(并已保存),git status 将显示文件正在修改,请参见上面添加的图像。
  • 当然,如果文件被修改,git status 会显示它已被修改。但是,如果一个文件没有被修改,那么 git status 仍然可以声称它已经被修改,因为如果干净的过滤器在工作目录中的版本。对吗?
  • 我将“更改”定义为文件发生的任何不同并被保存。例如,如果您删除一个空格并添加一个制表符 - 如果您只更改一个字符 - 并保存文档,这将构成根据 git 的更改。我的理解是,干净的过滤器实际上是在修改所有文件。因此,您必须手动将您一个人正在处理的所有文件添加到暂存区域 - 只有您自己知道。如果'它们都在同一个文件夹中,这很容易 - 只需将文件夹添加到暂存区域即可。希望这是有道理的?
  • 可能更容易创建一个文本文件,您可以继续将所有需要添加的文件重新粘贴到命令行中:例如git add file1.txt file2.txt etc 这可能是最简单的 - 假设你没有处理太多。
猜你喜欢
  • 2011-01-19
  • 2013-01-24
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 1970-01-01
相关资源
最近更新 更多