Почему исключенные файлы продолжают появляться в моем git sparse checkout?
Я использую зеркало git GCC и, поскольку я использую только внешние интерфейсы 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
Я не уверен, когда именно появятся файлы, я много переключаюсь на разные ветки (как удаленные, так и локальные), и это очень занятое репо, поэтому часто появляются новые изменения.
Как относительный новичок в 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
файл содержит ссылки на файлы в каталогах, которые должны быть исключены (т.е.!
) в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 в основном сказали: "это, вероятно, ошибка, никто не использует редкие проверки", но я надеюсь на лучший ответ;-)
Обновить:
В самый последний раз, когда я увидел, что проблема действительно произошла (то есть, файлов не было, а затем появилось после одной команды), выполнял извлечение из исходного потока:
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 дерево далеко впереди, и я думаю, что есть большая вероятность, что оно решит ваши проблемы.
В моем случае я выполнял некоторые юнит-тесты на репо с использованием разреженной проверки. В одном из моих тестовых случаев были созданы коммиты, которые содержали файлы, которые не были включены в мой список поддеревьев с разреженным оформлением заказа.
Когда я пытался git reset --hard 123456
Я получил следующую ошибку:
error: Entry 'a.c' not uptodate. Cannot update sparse checkout.
fatal: Could not reset index file to revision '123456'.
Решением было удалить файлы из моего рабочего дерева, повторно применив правила sparse-checkout:
git read-tree -mu HEAD
Проверьте, сохраняется ли проблема в последней версии Git 2.13 (второй квартал 2017 года, 5 лет спустя).
Любой файл skip-worktree больше не должен изменяться или даже просматриваться во время разреженной проверки, потому что:
preload-index
Код научили не беспокоить индексные записи, которые являются путями, которые не извлекаются "разреженным извлечением".
Смотрите коммит e596acc (10 февраля 2017 г.) Джеффа Хостетлера ( jeffhostetler
)
(Объединено Юнио С Хамано - gitster
- в коммите c7e234f, 27 февраля 2017 г.)
preload-index
: избегатьlstat
заskip-worktree
ПредметыУчат
preload-index
избежатьlstat()
вызовы записей индекса с установленным битом skip-worktree.
Это оптимизация производительности.Во время разреженной проверки бит пропуска рабочего дерева устанавливается для элементов, которые не были заполнены и, следовательно, отсутствуют в рабочем дереве.
Цикл предварительной загрузки для каждого потока выполняет серию тестов для каждой записи индекса, пытаясь сравнить версию рабочего дерева с индексом и пометить их как актуальные.
Этот патч сокращает эту работу.В системе Windows 10 с очень большим репо (индекс 450 МБ) и различными уровнями разреженности производительность была улучшена в
{preloadindex=true, fscache=false}
на 80% и в{preloadindex=true, fscache=true}
случай на 20% для различных команд.