TOC

Git 链接文件

Git 在团队协作的情况下容易遇到很多小问题,有一类是由于跨平台的系统差异导致的。有人习惯 Windows 下开发,有人习惯 Linux 下开发。

最常见的是这么四个问题:

  1. 文件权限问题
  2. 基本上我还没有遇到有需要给仓库中的文件设置权限的情况,但是由于权限的变更导致提交进来没有内容更改的文件就完全没有必要
  3. 所以非常必要设置 core.filemode false
  4. chmod 644 *.md
  5. 换行符问题
  6. Windows 新建的文件都是 \r\n 换行,Linux 则是 \n
  7. core.autocrlf true 可以在 checkout 的时候根据系统自动转换换行符
  8. 但是我觉得这个可能放到 hook 里面,在提交检查的时候一起做更加合适
  9. dos2unix *.md
  10. 软链接问题

  11. Linux 下的软链接切到 Windows 下之后,变成了一个普通文本,内容是链接的路径

  12. core.symlinks true 可以解决这个问题,这也是默认值,可是有些时候我们的环境中配置的就是 false
  13. 我的 Git for Windows 不知道为什么,system 配置就是设置成 false 了
  14. 有些情况下,项目配置似乎就默认是 false
  15. 如果已经成为现实了,软链是个文本,我们改配置,重新添加,然后 pull 到本地可以

core.symlinks
If false, symbolic links are checked out as small plain files that contain the link text. git-update-index and git-add will not change the recorded type to regular file. Useful on filesystems like FAT that do not support symbolic links.
The default is true, except git-clone or git-init will probe and set core.symlinks false if appropriate when the repository is created.

  1. 文件名大小写问题
  2. Linux 大小写敏感,比如 Apple.txt 和 apple.txt 可以在同一个目录,Windows 环境克隆下来,只能看到一个文件 apple.txt
  3. 没什么好的办法,应该也是在提交的时候作为风格检查
$ git config --list --global | grep sym
$ git config --list --system | grep sym
core.symlinks=false
$ git config --list --local | grep sym
core.symlinks=false

关于链接的另一个办法

CSDN 博客上看到 《windows上使用git仓库的问题(换行符、文件权限、软链接)》,里面提出下面这个思路。
虽然代码不够严谨,但是思路应该是没有问题的。以后遇到问题可以参考(还没有验证):

  1. 找出链接文件
  2. 创建 Windows 链接
  3. 操作索引区,忽略这个变更
import os

def rindex(lst, value):
    try:
        return lst.rindex(value)
    except ValueError:
        return -1

# find symbol link files or dirs
fp = os.popen("git ls-files -s | awk '/120000/{print $4}'")
links = fp.read().strip().split("\n")

# get symbol links' parent dir
link_dir = set()
for link in links:
    index = rindex(link, "/")
    if (index != -1):
        link_dir.add(link[:index])
    else:
        link_dir.add(".")

work_dir = os.getcwd()
# make link for every symbol link
for d in link_dir:
    os.chdir("/".join([work_dir,d]))
    fp = os.popen("ls -la")
    items = fp.read().strip().split("\n")
    for item in items:
        if "->" in item:
            tks = item.split("->")
            src = tks[0].strip().split(" ")[-1]
            dst = tks[1].strip().split("/")
            if (len(dst) > 1):
                dst = "\\\\".join(dst)
            else:
                dst = dst[0]
            print ("link " + src + " -> " + dst)
            os.popen("rm " + src)
            if (os.path.isfile(dst)):
                os.popen("cmd /c mklink /H " + src + " " + dst)
            else:
                os.popen("cmd /c mklink /j " + src + " " + dst)
            # make links unchanged
            os.popen("git update-index --assume-unchanged " + "/".join([os.getcwd(), src]))

参考资料与拓展阅读