Почему исключенные файлы продолжают появляться в моем git sparse checkout?

я использую GCC 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/

это работает некоторое время, но потом время от времени я замечаю, что некоторые из этих исключенных файлов вернулись, иногда много из них:

$ ls gnattools/
ChangeLog  configure  configure.ac  Makefile.in
$ ls  gcc/fortran/ | wc -l 
86

я не уверен, когда точно появятся файлы, я много переключаюсь на разные ветви (оба remote-tracking и local), и это очень занятое РЕПО, поэтому часто возникают новые изменения.

как относительный новичок в 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

я пробовал git read-tree -m -u HEAD но он ничего не делает.

Итак, мои вопросы:

  • почему файлы появляются снова?
  • как мне заставить их снова исчезнуть?
  • как я могу предотвратить их возвращение?
  • возможно, это связано с тем, что мой .git/info/exclude файл содержит ссылки к файлам в каталогах, которые должны быть исключены (т. е. названы с !) в ? Я последовал инструкциям игнорировать те же файлы, что и SVN

    $ git svn show-ignore >> .git/info/exclude

мой exclude файлы включают в себя пути, такие как

# /gcc/fortran/
/gcc/fortran/TAGS
/gcc/fortran/TAGS.sub
/gcc/fortran/gfortran.info*

который будет ниже одного из каталогов, названных в :

!gcc/fortran/

я попытался воспроизвести проблему с тестовым РЕПО, которое я клонирую несколько копий и редактировать каждый из них, создавать/переключать/удалять ветви и объединять изменения между ними, но это никогда не идет неправильно в моих игрушечных тестах. РЕПО GCC немного велико (более 2 ГБ), а время между "сбоями" (порядка недели или двух) слишком долго, чтобы ожидать, что люди попытаются точно воспроизвести проблему. Я!--27-->не экспериментировал с теми же путями в sparse-checkout и exclude, поскольку мне только сегодня пришло в голову, что там может быть конфликт.

I спросил об этом на #git на freenode несколько недель назад, и IIRC в основном сказал: "Это, вероятно, ошибка, никто не использует разреженную проверку", но я надеюсь на лучший ответ ; -)

обновление:

последний раз, когда я видел, что проблема действительно произошла (т. е. файлы не были там, а затем появились после одной команды), делал вытягивание из восходящего источника:

   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 директория отсутствовала, как и хотелось. После вытягивания, что dir присутствовал и эти файлы (и никакие другие) были под ним:

$ ls libgo/go/crypto/x509/root_<TAB>
root_darwin.go  root_stub.go    root_unix.go    

я не знаю, если переименованные файлы потеряли свои skip-worktree бит, как мне это проверить?

я уверен, что проблема не всегда возникает, когда есть переименования, потому что, например,libgfortran/ChangeLog файл, показанный в примере выше, не является новым файлом или недавно переименованным.

3 ответов


бит skip-worktree можно изменить с помощью git update-index --skip-worktree. Когда вы заметите, что файлы присутствуют, вы можете проверить git ls-files -v |grep ^S (s-файл, помеченный skip-worktree).

но, как говорят люди #git, если вы видите странное поведение, это, скорее всего, ошибка в git. В конце концов, это довольно эзотерическая функция. Вероятно, вы должны сообщить о своих выводах в список рассылки git.

редактировать: кроме того, если вы используете git 1.7.7.6, я настоятельно рекомендую обновить. 1.7.10 дерево способ впереди, и я думаю, что есть большой шанс, что это исправит ваши проблемы.


в моем случае я выполнял некоторые модульные тесты на репо, используя разреженную проверку. Один из моих тестовых случаев создал коммиты, содержащие файлы, которые не были включены в мой разреженный список под-дерева checkout.

когда я попытался git reset --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 (Q2 2017, 5 лет спустя).
Любой файл skip-worktree не должен быть изменен или даже просмотрен во время разреженной проверки, потому что:

на preload-index код был научен не беспокоиться об индексе записи, которые являются путями, которые не проверяются "разреженной выпиской".

посмотреть совершить e596acc (10 Feb 2017) by Джефф Хостетлер (jeffhostetler).
(слитый Junio C Hamano -- gitster -- на совершить c7e234f, 27 февраля 2017)

preload-index: во избежание lstat на skip-worktree предметы

научить preload-index избежать lstat() вызовы для индексных записей с набором битов skip-worktree.
Это оптимизация производительности.

во время разреженной проверки бит skip-worktree устанавливается для элементов этого не было. населены и поэтому не присутствуют в worktree.
Цикл preload-index для каждого потока выполняет серию тестов для каждой записи индекса, поскольку он пытается сравнить версию рабочего дерева с индексом и отметить их актуальными.
Этот патч сокращает работу.

в системе Windows 10 с очень большим РЕПО (индекс 450MB) и различными уровнями разреженности производительность была улучшена в {preloadindex=true, fscache=false} случай 80% и в {preloadindex=true, fscache=true} случай 20% для различного команды.