Отмените git update-index --no-предположить-неизмененный (не работает) и сможете снова увидеть эти локальные изменения

Обновление: Мои проблемы с разрешениями каким-то образом исправились произвольно, поскольку теперь работает та же команда создания удаленной ветви, поэтому (как вы, наверное, догадались) это не было вызвано этой проблемой отслеживания.

Сейчас я просто пытаюсь решить проблему с отслеживанием. Спасибо!

Оригинал: я изначально применил следующее к нескольким файлам:

    git update-index --assume-unchanged filename.py

ссылаясь на эту документацию:

https://git-scm.com/docs/git-update-index

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

Затем я столкнулся с некоторыми проблемами, выдвигающими удаленную ветку, которой раньше не было, стандарт

    fatal: Could not read from remote repository.

    Please make sure you have the correct access rights
    and the repository exists. 

Итак, учитывая, что у меня не было проблем с доступом прямо перед запуском update-indexЯ решил вернуть это --assume-unchanged так как я не делал никаких других проблем с моим git-репо.

Я был в состоянии просмотреть эти assume-unchanged файлы, использующие

    git ls-files -v | grep '^[a-z]'

Я пытался вернуть assume-unchanged используя

    git update-index --really-refresh

как указано здесь на возвращение assume-unchanged через несколько файлов:

Отменить git update-index --assume-unchanged

Это не восстановило их, и я тогда попробовал

    git ls-files -v | grep '^[a-z]' | cut -c 3- | tr '\012' '\000' | xargs -0 git update-index --no-assume-unchanged

согласно этой рекомендации:

Отменить git update-index --assume-unchanged

Файлы все еще невидимы, и теперь я больше не могу их просматривать, запустив

    git ls-files -v | grep '^[a-z]'

Я также экспериментально попытался сделать это на одном из моих файлов:

    git update-index --skip-worktree file.py

согласно здесь

https://git-scm.com/docs/git-update-index

насколько я знаю skip-worktree берет на себя assume-unchanged поэтому я надеялся увидеть какое-то изменение состояния в этом файле. Еще ничего.

Как мне восстановить файлы, чтобы они стали видимыми, а изменения отслеживаются в моем рабочем каталоге?

И в качестве дополнительного вопроса, есть ли идеи, как это могло повлиять на мои права доступа для создания новой удаленной ветви?

1 ответ

У вас есть две разные проблемы здесь. Твой fatal: Could not read from remote repository Ошибка совершенно не зависит от битов флага, которые вы установили или очистили в своем индексе. Это подразумевает, что либо:

  • для любого протокола, который вы используете для доступа к другому хранилищу (http, https, ssh://, или же git://), соединение с другим Git не удалось, или
  • соединение установилось успешно, но затем другой хост, который предположительно содержит этот другой Git-репозиторий, сказал "Я не вижу Git-репозиторий здесь" (в остальной части URL).

Если само соединение не удалось, вы должны увидеть дополнительную информацию до fatal: линия, сообщающая вам, что произошло, например, не удалось разрешить имя хоста в IP-адрес, имя пользователя и / или пароль требуется, но отсутствует, и так далее. Используйте это для диагностики плохих соединений. Если соединение установилось успешно, но хост говорит "здесь нет Git-репо", используйте любую информацию, которую вы можете получить о хосте, чтобы узнать, куда пошел репозиторий (например, можете ли вы войти на хост напрямую и покопаться?).


Теперь, что касается assume-unchanged а также skip-worktree немного, я боюсь, что это становится немного сложным и техническим. Вам нужно знать кое-что из этого, чтобы использовать Git, так что стоит поработать. Я также отмечу здесь, что совет использовать --really-refresh в принципе неправильно. Это временно игнорирует assume-unchanged бит для обновления кэшированных данных статистики в индексе, но не влияет на фактический предполагаемый бит без изменений. Способ очистить этот бит действительно использовать --no-assume-unchanged как в приведенном выше модном конвейере, который заканчивается | xargs -0 git update-index --no-assume-unchanged, То же самое относится к биту skip-worktree, за исключением того, что вы очищаете его --no-skip-worktree, 1

Что такое индекс и что это git update-index команды делают?

При работе с Git важно понимать, что у вас есть три вещи, которые я всегда называю активными копиями каждого файла. 2 Одна из этих трех копий - это то, что было в коммите, который вы проверили. Эта копия только для чтения. Вы не можете изменить его: он зафиксирован в коммите и останется там, в этом коммите, пока этот коммит существует - по сути, навсегда. 3 Это означает, что замороженная копия безопасна: ничто из того, что вы делаете, не будет ее засорять; Вы всегда можете получить его обратно. Для просмотра замороженной копии файла с именем path/to/file.ext использовать git show HEAD:path/to/file.ext , Этот HEAD:file синтаксис работает с git show и позволяет увидеть замороженную копию в текущем коммите. (Вы также можете увидеть замороженную копию в любом другом коммите.)

Теперь эти замороженные копии находятся в специальном, только для чтения, сжатом формате Git. Ни одна из других программ на вашем компьютере не может получить к ним доступ напрямую (если они не слишком много узнали о внутренностях Git). И, поскольку они не могут быть изменены, они хороши для архивирования, но совершенно бесполезны для выполнения любой новой работы. Итак, когда вы git checkout Git извлекает все замороженные файлы, превращая их в обычные повседневные файлы, которые вы можете видеть и работать с ними как обычно. Вы можете изменить эти обычные файлы для чтения / записи или делать с ними все, что захотите, включая добавление новых и удаление существующих, все обычным способом, который вы делаете с компьютером.

Эти пригодные для использования файлы находятся в том, что Git называет вашим рабочим деревом. Вот где вы делаете свою работу. Это вторая копия каждого файла. Вам не нужно делать ничего особенного: это просто файлы. Если вы хотите посмотреть на файл с именем file используйте любые инструменты (редактор, средство просмотра файлов и т. д.), которые вы всегда используете для просмотра файла с именем file, Его зовут просто file,

Третья копия каждого файла, где Git становится хитрым. Здесь и начинается индекс. Индекс также называется промежуточной областью, а иногда - редко в наши дни - кэшем. Это все имена для одного и того же. Третья копия каждого файла находится в индексе, и вы можете просмотреть индексную копию файла с именем file с помощью git show :file, Это, git show перед двоеточием подразумевается: покажи мне копию в индексе. git ls-files Команда, которую вы использовали в причудливом конвейере, также перечисляет, что находится в индексе.

Третья копия файла находится в формате, который Git использует для постоянного хранения замороженных файлов, но не совсем заморожена. Вы можете в любое время перезаписать его. Вы можете заменить индексную копию file с любым новым контентом, который вам нравится. Вы делаете это с git add, которые берут копию рабочего дерева - предположительно, вы уже изменили эту копию - и заменяете индексную копию этой версией. Или, если хотите, вы можете удалить индексную копию file, с помощью git rm, который удаляет как индексную копию, так и копию рабочего дерева.

Технически, в индексе есть только много данных из кэша о файле, а также несколько флагов, а также ссылка на сохраненную копию файла в замороженном формате. Когда вы впервые проверяете коммит, чтобы ваш HEAD и копии рабочего дерева совпадают, ваша индексная копия действительно просто повторно использует замороженные HEAD скопируйте напрямую, так что это не займет лишнего места вообще. Когда вы используете git add чтобы перезаписать его, Git берет копию рабочего дерева, сжимает ее в замороженную, готовую к постоянному хранению копию, помещает эту копию куда-то в 4 и обновляет ссылку на индекс.

Это один из секретов, который делает git commit так быстро. Git не должен смотреть на ваше рабочее дерево. Не нужно повторно сжимать все ваши файлы. Они уже там, в вашем индексе, готовы к работе. Все git commit необходимо упаковать предварительно замороженные файлы в коммит. Он просто фиксирует все, что есть в вашем индексе во время выполнения git commit, Следовательно, хороший способ думать об этом состоит в том, что индекс - это ваш следующий предложенный коммит. какая git add а также git rm сделать это обновить предложенный коммит. Бег git commit просто сделайте снимки того, что находится в вашем индексе - в промежуточной области, готово для фиксации - даже если это в основном то же самое, что и предыдущий коммит. git add а также git rm Команды - это то, что фактически обновляет индекс.

Вот почему и как каждый коммит является полным снимком каждого файла. Любой файл, который вы не обновляете, все еще находится в индексе ("на стадии") и будет в следующем коммите.

git status использует флаги

Предположим, у вас есть 3000 файлов в проверенном в данный момент коммите (и, следовательно, в вашем рабочем дереве), и вы изменили один в своем рабочем дереве и git add чтобы получить обновление в вашем индексе / промежуточной области. Если вы бежите git status в настоящее время, git status не потрудился сказать вам, что 2999 из ваших 3000 файлов совпадают, так как это бесполезная информация. какая git status говорит вам, что один файл обновлен.

Путь git status Для этого, по крайней мере, в принципе, нужно выполнить два отдельных сравнения:

  • Первый, git status будет сравнивать каждый файл в HEAD зафиксировать копию в индексе. Для каждого файла, который здесь одинаков, ничего не сказано. Но если файл здесь другой, он говорит: готовится к коммиту.

  • Следующий, git status будет сравнивать каждый файл в индексе с копией в рабочем дереве. Опять же, если файлы одинаковые, это ничего не говорит. Если файлы разные, там написано: не подготовлено для коммита.

когда git status Если сравнить это, то первая часть идет довольно быстро из-за внутреннего представления Git содержимого файла в виде хеш-идентификаторов BLOB-объектов. Так что, в буквальном смысле, просто сравнивает каждый файл. Это займет всего несколько миллисекунд, чтобы решить, что 2999 из 3000 файлов одинаковы и один отличается. Но вторая часть медленная: на самом деле сравнение всех 3000 файлов может занять несколько секунд!

Так, git status читы. Это где аспект кэша индекса вступает в игру. Каждая запись индекса содержит ссылку на файл замороженного формата, который готов к фиксации; но он также содержит некоторые данные, полученные в результате ОС lstat системный вызов. 5 Git может сделать другое lstat системный вызов файла в рабочем дереве. В большинстве случаев в результате stat данные совпадают с тем, что Git сохранял ранее, только в том случае, если файл в рабочем дереве по- прежнему совпадает с копией, которую Git имеет в замороженном формате, как это кэшируется в записи индекса. Если вы изменили копию рабочего дерева, ОС обновит stat данные также.

Итак, представьте, что вы git status, сравнивая каждый файл в индексе с его копией в рабочем дереве, так что вы можете сказать, что он не подготовлен для фиксации, если это необходимо. Вы можете открыть каждый файл рабочего дерева и прочитать его полностью, и сравнить его содержимое с тем, что вы получите, если распакуете замороженную индексную копию. Это скажет вам, если они одинаковые или разные, но вау, это большая работа, это может занять несколько секунд. Но у вас есть это в кеше stat данные, и если вы сравните данные статистики с результатом другого lstat Ну, это занимает гораздо меньше времени и работы. Таким образом, вы делаете это вместо этого. Если lstat Результаты соответствуют кэшированным результатам, файл должен быть таким же, и вы можете ничего не говорить и переходить к следующему файлу.

Но на самом деле каждый lstat Системный вызов также довольно медленный. Конечно, это в тысячи раз быстрее, чем чтение каждого файла, но это может занять сотни микросекунд. А что, если у ОС действительно ужасно медленно lstat что занимает 3 миллисекунды? Выполнение этого для 3000 файлов, если каждый занимает 3 миллисекунды, займет девять секунд, а это слишком долго!

У Git есть флаг для этого. --assume-unchanged flag, который является устанавливаемым флагом в каждой записи индекса, говорит Git: не беспокойтесь о вызове lstat в этой копии рабочего дерева просто предположим, что она соответствует кэшированным данным статистики. У него есть второй, немного более мощный флаг, --skip-worktree, который достигает того же результата. (Это немного более мощный, потому что некоторые команды, такие как git update-index --really-refresh, будет игнорировать первый флаг, но не второй.)

Если вы установите любой бит, операции, которые будут сравнивать кэшированный индекс stat данные против реальных stat данные из рабочего дерева, чтобы сказать, действительно ли файл был изменен, просто предположим, что файл не был изменен. Очистите оба бита, и эти операции Git вызовут stat после всего. затем git status должно увидеть обновление файла, если stat данные, которые возвращает ОС, также обновляются. Есть приемы уровня ОС, которые побеждают это, но вы обычно можете победить эти приемы уровня ОС, используя touch:

touch path/to/file

удостоверяется, что stat данные о path/to/file теперь новее любого кешируемого stat данные, которые Git может хранить.

Эта картина должна быть достаточно ясной, если она немного сложная: область индекса / промежуточного хранения содержит кэшированные данные о каждом файле рабочего дерева из предыдущего lstat системный вызов. Если кэшированные данные соответствуют тому, что ОС сообщает о новом lstat вызов, копия индекса должна соответствовать копии рабочего дерева. Если вы установите биты флага, Git не потрудится сделать lstat call: он просто предполагает, что два набора данных совпадают, так что индексная копия совпадает с копией рабочего дерева, действительно ли это так. Очистить биты и Git возвращается к вызову lstat и получает - мы надеемся - точный отчет от ОС.

Эта картина больше не является полностью верной, поскольку Git теперь также имеет возможность использовать монитор файловой системы, чтобы избежать вызова lstat без необходимости. Но это тема для другого вопроса полностью.


1 Обратите внимание, что модный конвейер предполагает, что у вас есть LC_COLLATE установлен в C в какой-то версии grep подчиняться LC_COLLATE флаг. Это:

git ls-files -v | grep '^[a-z]'

может перечислить каждый файл в зависимости от LC_COLLATE, В нем также перечислены --skip-worktree файлы, но вы должны сбросить этот флаг с отдельным git update-index --no-skip-worktree команда. Это одна из причин, по которой я написал git-flagged, (Перечисление слишком много файлов из-за grep слишком большое совпадение безвредно: просто git update-index команды, которые на самом деле не нужно запускать.)

Я не сделал мой git-flagged Скрипт поддерживает новые / недействительные биты fsmonitor. Если ваша система использует fsmonitor, и это идет не так, у вас есть большая проблема, и, возможно, вам следует отключить fsmonitor глобально, через git config и core.fsmonitor установка.

2 Это предполагает нормальное (не --bare), и что вы не добавили дополнительные рабочие деревья, используя git worktree add, Каждое рабочее дерево, которое вы добавляете git worktree add получает свой собственный индекс и рабочее дерево и свой собственный HEAD Таким образом, каждый получает еще три из этих активных копий.

3 После того, как вы сделаете коммит и получите определенный хеш-код, вы можете использовать этот хеш-код, чтобы увидеть, существует ли коммит еще. Если он существует - и, вероятно, существует, - то файлы, в которые вы его заморозили, также все еще существуют в этой замороженной форме.

Сложно на самом деле избавиться от плохого коммита. Это может быть сделано, так что коммиты не обязательно вечны, но это своего рода способ думать о них.

4 "Где-то" на самом деле прямо в хранилище. Если вы фиксируете эту копию файла, замороженная копия используется; если нет, то часто Git в конечном итоге очищается от мусора. Если у вас постоянно слишком мало места на диске, вам не нужно беспокоиться об этих вещах, которые git fsck покажет как свисающие капли. Просто позвольте Git вычистить их позже, самостоятельно.

5 Это относится конкретно к POSIX lstat системный вызов, который производит stat данные. Если ваша базовая ОС не имеет или не использует stat данные, Git все еще должен что-то кешировать, и будет использовать какой-то синтетический stat данные, которые должны быть достаточно хороши, чтобы сделать остальную часть этой работы.

Другие вопросы по тегам