代码之家  ›  专栏  ›  技术社区  ›  Alex

Git如何处理符号链接?

  •  1401
  • Alex  · 技术社区  · 15 年前

    如果我有一个作为符号链接的文件或目录,并将其提交到Git存储库,它会发生什么?

    我假设它将其作为符号链接保留,直到文件被删除,然后如果您从旧版本中提取文件,它只会创建一个普通文件。

    3 回复  |  直到 6 年前
        1
  •  1490
  •   Peter Mortensen Mohit    6 年前

    Git只是将链接的内容(即它链接到的文件系统对象的路径)存储在一个“blob”中,就像普通文件一样。然后,它将名称、模式和类型(包括它是符号链接的事实)存储在表示其包含目录的树对象中。

    签出包含链接的树时,无论目标文件系统对象是否存在,它都会将对象还原为符号链接。

    如果删除符号链接引用的文件,则不会以任何方式影响Git控制的符号链接。你会有一份悬而未决的推荐信。如果需要,用户可以删除或更改链接以指向有效的内容。

        2
  •  340
  •   Dmitry Minkovsky    3 年前

    通过将符号链接添加到索引中,可以看到Git对符号链接的作用。索引类似于预提交。提交索引后,可以使用 git checkout 将索引中的所有内容返回到工作目录。那么,当您向索引添加符号链接时,Git会做什么呢?

    $ ln -s /path/referenced/by/symlink symlink
    

    git ls-files 允许您检查索引( -s 印刷品 stat

    $ git ls-files -s ./symlink
    [nothing]
    

    现在,将符号链接添加到索引。将文件添加到索引时,Git会将其内容复制到对象存储中。

    $ git add ./symlink
    

    那么,增加了什么?

    $ git ls-files -s ./symlink
    120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink
    

    .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c 如果你检查这个文件,你会发现它非常小。它不存储链接文件的内容。要确认这一点,请使用打印压缩存储库对象的内容 git cat-file :

    $ git cat-file -p 1596f9db1b9610f238b78dd168ae33faa2dec15c
    /path/referenced/by/symlink
    

    120000 模式是否在中列出 ls-files 输出大概是 100644 对于常规文件。)

    core.symlinks 配置。从…起 man git-config

    core.symlinks

    如果为false,则符号链接将作为包含链接文本的小纯文件检出。

    core.symlinks 配置。

    当然是在存储库中)。

        3
  •  152
  •   Peter Mortensen Mohit    6 年前

    编者按:这篇文章可能包含过时的信息。请参阅评论和建议 this question 关于Git自1.6.1以来的变化。

    重要的是要注意当有一个目录是软链接时会发生什么。 任何带有更新的Git拉取都会删除链接并使其成为普通目录。这是我通过艰苦的方式学到的。一些见解 here here.

     ls -l
     lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir
    

    git add/commit/push

    It remains the same
    

    之后 git pull 发现了一些更新

     drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir
    
        4
  •  0
  •   VonC    3 年前

    特例:何时" git checkout ( man ) 删除一个在它要签出的提交中不存在的路径,它没有足够小心地不遵循符号链接,这已经用Git 2.32(2021年第2季度)进行了更正。

    commit fab78a0 , commit 462b4e8 Matheus Tavares ( matheustavares ) .
    (由合并) Junio C Hamano -- gitster -- commit 9210c68 ,2021年3月30日)

    checkout

    签字人:Matheus Tavares

    1d718a5 (“不要覆盖未跟踪的符号链接”,2011-02-20,Git v1.7.5-rc0-- merge ), symlink.c :check_leading_path()开始为返回不同的代码 FL_ENOENT FL_SYMLINK .
    但是其中一个呼叫者, unlink_entry() ,未对此更改进行调整,因此它开始跟随要删除条目的前导路径上的符号链接。

    因为我们不再尝试取消这些路径的链接,我们也不会从中得到警告 remove_or_warn() .

    删除我们要签出到的状态中不再存在的跟踪路径。

    当然,我们将在路径的dirname处留下一个常规文件或符号链接,但该文件现在未被跟踪(因此,无需警告),或者在下一个签出阶段将被跟踪文件替换