为什么被排除的文件总是出现在我的git稀疏签出中? 我使用这个,因为我只使用C和C++前端,所以我使用Git的稀疏签出功能来排除我不需要的几百个文件: $ git config core.sparseCheckout true $ cat .git/info/sparse-checkout /* !gnattools/ !libada/ !libgfortran/ !libgo/ !libjava/ !libobjc/ !libquadmath/ !gcc/ada/ !gcc/fortran/ !gcc/go/ !gcc/java/ !gcc/objc/ !gcc/objcp/ !gcc/testsuite/ada/ !gcc/testsuite/gfortran.dg/ !gcc/testsuite/gfortran.fortran-torture/ !gcc/testsuite/gnat.dg/ !gcc/testsuite/go.dg/ !gcc/testsuite/go.go-torture/ !gcc/testsuite/go.test/ !gcc/testsuite/objc/ !gcc/testsuite/objc.dg/ !gcc/testsuite/obj-c++.dg/ !gcc/testsuite/objc-obj-c++-shared/

为什么被排除的文件总是出现在我的git稀疏签出中? 我使用这个,因为我只使用C和C++前端,所以我使用Git的稀疏签出功能来排除我不需要的几百个文件: $ git config core.sparseCheckout true $ cat .git/info/sparse-checkout /* !gnattools/ !libada/ !libgfortran/ !libgo/ !libjava/ !libobjc/ !libquadmath/ !gcc/ada/ !gcc/fortran/ !gcc/go/ !gcc/java/ !gcc/objc/ !gcc/objcp/ !gcc/testsuite/ada/ !gcc/testsuite/gfortran.dg/ !gcc/testsuite/gfortran.fortran-torture/ !gcc/testsuite/gnat.dg/ !gcc/testsuite/go.dg/ !gcc/testsuite/go.go-torture/ !gcc/testsuite/go.test/ !gcc/testsuite/objc/ !gcc/testsuite/objc.dg/ !gcc/testsuite/obj-c++.dg/ !gcc/testsuite/objc-obj-c++-shared/,git,sparse-checkout,Git,Sparse Checkout,这在一段时间内有效,但我不时注意到一些被排除的文件已返回,有时返回的文件很多: 我不确定文件何时重新出现,我经常切换到不同的分支(远程跟踪和本地),这是一个非常繁忙的回购,因此需要频繁地进行新的更改 作为git的新手,我不知道如何“重置”我的工作树以再次删除这些文件 作为一个实验,我尝试禁用稀疏签出和拉取,认为我可以在之后再次启用sparseCheckout以某种方式更新树,但效果不太好: $ git config core.sparseCheckout false $ git config c

这在一段时间内有效,但我不时注意到一些被排除的文件已返回,有时返回的文件很多:

我不确定文件何时重新出现,我经常切换到不同的分支(远程跟踪和本地),这是一个非常繁忙的回购,因此需要频繁地进行新的更改

作为git的新手,我不知道如何“重置”我的工作树以再次删除这些文件

作为一个实验,我尝试禁用稀疏签出和拉取,认为我可以在之后再次启用sparseCheckout以某种方式更新树,但效果不太好:

$ git config core.sparseCheckout false
$ git config core.sparseCheckout 
false
$ git pull
remote: Counting objects: 276, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 117 (delta 98), reused 0 (delta 0)
Receiving objects: 100% (117/117), 64.05 KiB, done.
Resolving deltas: 100% (98/98), completed with 64 local objects.
From git://gcc.gnu.org/git/gcc
   7618909..0984ea0  gcc-4_5-branch -> origin/gcc-4_5-branch
   b96fd63..bb95412  gcc-4_6-branch -> origin/gcc-4_6-branch
   d2cdd74..2e8ef12  gcc-4_7-branch -> origin/gcc-4_7-branch
   c62ec2b..fd9cb2c  master     -> origin/master
   2e2713b..29daec8  melt-branch -> origin/melt-branch
   c62ec2b..fd9cb2c  trunk      -> origin/trunk
Updating c62ec2b..fd9cb2c
error: Your local changes to the following files would be overwritten by merge:
        gcc/fortran/ChangeLog
        gcc/fortran/iresolve.c
        libgfortran/ChangeLog
        libgfortran/io/intrinsics.c
Please, commit your changes or stash them before you can merge.
Aborting
所以很明显,我对我从未要求过的文件进行了本地修改,而AFAIK也从未接触过

但是
git status
没有显示这些更改:

$ git st
# On branch master
# Your branch is behind 'origin/master' by 9 commits, and can be fast-forwarded.
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       libstdc++-v3/53270.txt
#       libstdc++-v3/TODO
它将位于
稀疏签出
文件中命名的一个目录下:

!gcc/fortran/
我曾经尝试用一个测试repo来重现这个问题,我克隆了几个副本并编辑它们,创建/切换/删除分支,并在它们之间合并更改,但在我的玩具测试用例中它从来没有出错。GCC回购协议有点大(超过2GB),而且“失败”之间的间隔时间(大约一到两周)太长,无法期望人们尝试准确重现问题。我没有尝试过在
稀疏签出
排除
中使用相同的路径,因为我今天才意识到可能存在冲突

几周前,我在freenode上的git上问过这个问题,IIRC基本上被告知“这可能是一个bug,没有人使用稀疏签出”,但我希望得到更好的答案;-)

更新:

我最近一次看到问题实际发生(即文件不在那里,然后在一个命令后出现)是从上游原点进行拉取:

   bac6f1f..6c760a6  master     -> origin/master
显示的更改包括以下重命名:

 create mode 100644 libgo/go/crypto/x509/root.go
 rename libgo/go/crypto/{tls => x509}/root_darwin.go (90%)
 rename libgo/go/crypto/{tls => x509}/root_stub.go (51%)
 rename libgo/go/crypto/{tls => x509}/root_unix.go (76%)
 create mode 100644 libgo/go/crypto/x509/root_windows.go
在拉取之前,根据需要,
libgo
目录不存在。拉取后,目录存在,并且这些文件(没有其他文件)在目录下:

$ ls libgo/go/crypto/x509/root_<TAB>
root_darwin.go  root_stub.go    root_unix.go    
$ls libgo/go/crypto/x509/root_
root\u darwin.go root\u stub.go root\u unix.go
我不知道重命名的文件是否丢失了
跳过工作树
位,如何检查


我敢肯定,当有重命名时,问题并不总是发生,因为例如,上面示例中显示的
libgfortran/ChangeLog
文件不是新文件或最近重命名的文件。

跳过工作树位可以使用
git更新索引--skip worktree
修改。当您注意到存在的文件时,您可以检查git ls files-v|grep^S(S是一个标记为跳过工作树的文件)

但正如git的人所说,如果你看到奇怪的行为,很可能是git中的一个bug。毕竟,这是一个相当深奥的特征。您可能应该向git邮件列表报告您的发现


编辑:另外,如果您使用的是git 1.7.7.6,我强烈建议升级。1.7.10 tree遥遥领先,我认为它很有可能解决您的问题。

在我的案例中,我使用稀疏签出对回购协议执行了一些单元测试。我的一个测试用例创建了包含稀疏签出子树列表中未包含的文件的提交

当我试图
git重置--hard 123456
时,收到以下错误:

error: Entry 'a.c' not uptodate. Cannot update sparse checkout.
fatal: Could not reset index file to revision '123456'.
解决方案是通过重新应用稀疏签出规则来删除我的工作树中的文件:

git read-tree -mu HEAD

检查最新的Git 2.13(2017年第二季度,5年后)中是否存在该问题。
在稀疏签出期间,不应再修改甚至查看任何跳过的工作树文件,因为:

人们已经教导他们不要为索引操心 未通过“稀疏签出”签出的路径项

参见(2017年2月10日)作者。
(于2017年2月27日被合并)

预加载索引
:避免
跳过工作树
项的
lstat
设定
preload index
以避免
lstat()
调用设置了跳过工作树位的索引项。
这是一个性能优化

在稀疏签出期间,将在项目上设置跳过工作树位 未填充的,因此不存在于 工作树。
每线程预加载索引循环在尝试将工作树版本与索引进行比较并将其标记为最新时,对每个索引项执行一系列测试。
这个补丁缩短了这项工作

在具有非常大的repo(450MB索引)和各种稀疏级别的Windows 10系统上,各种命令的
{preload index=true,fscache=false}
情况下性能提高了80%,而
{preload index=true,fscache=true}
情况下性能提高了20%


对于Git2.27(2020年第2季度),“
稀疏签出
”以不同的方式管理跳过工作树

参见,,,,,,,,,,,(2020年3月27日)作者。
(于2020年4月29日合并)

:未能设置
跳过\u工作树
位始终只是一个警告 审核人:Derrick Stolee
签字人:以利亚·纽伦

设置和清除
SKIP_WORKTREE
位不仅在用户运行“稀疏签出”时完成;“checkout”等其他命令也通过
unpack_trees()
运行,该命令具有处理此特殊位的逻辑。因此,我们需要考虑他们如何处理特殊情况。 几个比较点应该有助于解释更改
unpack_trees()
如何处理这些位的基本原理:

  • 暂时忽略稀疏签出,如果您正在切换分支并且有脏的更改,则只会将其视为阻止分支切换的错误
    error: Entry 'a.c' not uptodate. Cannot update sparse checkout.
    fatal: Could not reset index file to revision '123456'.
    
    git read-tree -mu HEAD
    
    error: The following untracked working tree files would be overwritten by checkout:
    
    warning: The following paths were already present and thus not updated despite sparse patterns: