Почему исключенные файлы продолжают появляться в моем разреженном разрешении git?
Я использую GCC git mirror, и поскольку я использую только контуры 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
Я не уверен, что когда файлы снова появятся, я много перейду на разные ветки (как удаленное отслеживание, так и локальное), и это очень загруженное репо, поэтому есть новые изменения, которые можно часто вытаскивать.
Как относительный новичок в git, я не знаю, как "reset" мое дерево работы снова избавиться от этих файлов.
В качестве эксперимента я попытался отключить разреженную проверку и потянув, думая, что смогу снова включить 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
содержит ссылки на файлы в каталогах, которые должны быть исключены (т.е. с именем !
) в файле sparse-checkout
? Я выполнил инструкции игнорировать те же файлы, что и SVN
$ git svn show-ignore >> .git/info/exclude
Итак, мои файлы exclude
включают в себя такие пути, как
# /gcc/fortran/
/gcc/fortran/TAGS
/gcc/fortran/TAGS.sub
/gcc/fortran/gfortran.info*
Что будет ниже одной из каталогов, названных в файле sparse-checkout
:
!gcc/fortran/
Я попытался воспроизвести проблему с тестовым репо, в котором я клонировал несколько копий и редактировал каждую из них, создавал/переключал/удалял ветки и менял изменения между ними, но в моих игрушечных тестах это не пошло не так. Репо GCC немного больше (более 2 ГБ), а время между "неудачами" (порядка недели или двух) слишком долго, чтобы люди пытались воспроизвести проблему точно. Я не экспериментировал с одинаковыми путями в sparse-checkout
и exclude
, так как это имело место для меня сегодня, там может быть конфликт.
Я спросил об этом на # git на freenode несколько недель назад, а в IIRC в основном сказали: "Это, вероятно, ошибка, никто не использует редкую проверку", но я надеюсь на лучший ответ;)
Update:
В последний раз, когда я увидел, что проблема на самом деле происходит (т.е. файлы не были там, а затем появились после одной команды) делали pull из восходящего источника:
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
Я не знаю, потеряли ли переименованные файлы бит skip-worktree
, как это проверить?
Я уверен, что проблема не всегда возникает, когда есть переименования, потому что, например, файл libgfortran/ChangeLog
, показанный в приведенном выше примере, не является новым или недавно переименован.
Ответы
Ответ 1
Бит скип-рабочей строки может быть изменен с помощью 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 дерево впереди, и я думаю, что есть большая вероятность, что он исправит ваши проблемы.
Ответ 2
В моем случае я выполнял некоторые модульные тесты на репо, используя редкую проверку. Один из моих тестовых примеров создал коммиты, содержащие файлы, которые не были включены в список разреженных разрешений.
Когда я попытался 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
Ответ 3
Проверьте, сохраняется ли проблема в последнем Git 2.13 (Q2 2017, 5 лет спустя).
Любой файл skip-worktree не должен быть изменен или даже просмотрен во время разреженной проверки, потому что:
preload-index
code учили не беспокоиться об индексе записи, которые являются путями, которые не проверяются "разреженной проверкой".
См. совершить e596acc (10 февраля 2017 г.) Jeff Hostetler (jeffhostetler
).
(слияние Junio C Hamano - gitster
- в commit c7e234f, 27 февраля 2017 г.)
preload-index
: избегать lstat
для skip-worktree
элементов
Учите preload-index
, чтобы избежать lstat()
вызовов для записей индекса с установленным битом скипа. Это оптимизация производительности.
Во время разреженной проверки бит скинов-скинов работает на элементах которые не были заселены и, следовательно, отсутствуют в worktree.
Цикл индекса предварительной загрузки для каждой строки выполняет серию тестов для каждой записи индекса, поскольку он пытается сравнить версию рабочей строки с индексом и пометить их актуальными.
Этот патч сокращает время работы.
В системе Windows 10 с очень большим репо (индекс 450 МБ) и различными уровнями разреженности производительность была улучшена в случае {preloadindex=true, fscache=false}
на 80%, а в случае {preloadindex=true, fscache=true}
- на 20% для различных команд.