Не может помешать git изменять файлы после rm --cached - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь запустить ' git rm -rf --cached. ' вместе с ' git add. ', чтобы удалить кэшированные файлы, которые теперь перечислены в .gitignore.Я использую Visual Studio на компьютере с Windows и предпочитаю оставлять окончания строк такими же, как они для этой конкретной ситуации.

Я попытался установить для core.autocrlf значение false, используя команду git config.Я попытался создать .gitattributes со строкой '* -text', запустив .git / index и запустив git reset .Пока что каждый раз, когда я добавляю файлы обратно, я получаю огромный список измененных файлов.

РЕДАКТИРОВАТЬ: изменение в файлах на самом деле не окончание строк, это изменения в разрешениях файлов, которые я не запрашивал.

1 Ответ

0 голосов
/ 12 сентября 2018

Редактировать: остающаяся проблема заключается в том, что режимы файлов, по-видимому, неправильно сохраняются в системах Windows (см. Также Что такое "файловый режим" в git? ).Чтобы сохранить и восстановить их, понадобится сценарий плюс исходные данные:

git ls-files --stage > /tmp/original

Для восстановления режимов этот довольно грубый конвейер должен работать:

< /tmp/original \
awk -F$'\t' '/^100755 / { print "git update-index --chmod=+x \"" $2 "\"" }' |
sh

Это попытаетсядо chmod +x файлов, которые были удалены по приведенной ниже последовательности, поэтому вы можете ожидать появления некоторых сообщений об ошибках, если такие файлы есть.(Предполагается также, что ни у одного файла нет двойных кавычек в именах.)


Если у вас еще нет файла .gitattributes, вот шестиступенчатый процесс, который должен работать:

  1. Создайте этот файл .gitattributes так же, как вы это сделали
  2. Выполнить rm .git/index
  3. Выполнить git checkout HEAD -- .
  4. Выполнить git rm -r --cached .
  5. Выполните git add .
  6. Выполните git rm .gitattributes (вы можете оставить это до тех пор, пока не убедитесь, что все работает).Запустите git commit позже.

У меня нет (и не использую) Windows, поэтому я не могу проверить это, но вот теория, почему она должна работать, и, следовательно, почему существуют эти шаги.

Фактический формат хранения данных Git - это специальный, только для Git, сжатый (иногда сильно сжатый) формат.Файлы, хранящиеся в этом формате, в основном полезны только для самого Git.Этот формат хранит необработанный, не интерпретируемый поток байтов: файлы не нужно разделять на «текст» и «данные» и т. Д., Они являются просто необработанными потоками байтов (следовательно, рассматриваются как «данные» / «нетекстовые»).После сохранения данные доступны только для чтения и им присваивается хэш-идентификатор (в настоящее время SHA-1, хотя в будущем Git может использовать SHA-256).Git называет файл, хранящийся таким образом, blob , что является термином, украденным из мира баз данных .

Формат хранения полезных файлов на вашем компьютере, конечно, отличаетсяи может (и делает это в Windows) сделать различие между «текстом» и «данными».Текст может иметь кодировки (например, ISO-8859-1, UTF-8, UTF-16 и т. Д.).Эти файлы обычно доступны для чтения и записи, и с ними может справиться все, что угодно на вашем компьютере (в какой-то степени, в зависимости от кодировки).

Git должен извлекать файлы из коммитов, превращая их из больших двоичных объектов в файлы, которые выможет работать сЭти файлы находятся в вашем рабочем дереве .Вы работаете с ними, а затем git add с ними, чтобы дать Git возможность повторно их блобизировать.

Между этими специальными BLOB-объектами только для Git и рабочим деревом Git требуется место для хранения.данные большого двоичного объекта, которые, в отличие от коммита, доступны для записи, но, как и коммит, имеют файл в специальном формате Git-only.Это промежуточное место - Git's index .Различные фрагменты документации Git иногда называют это промежуточной областью или кеш .

Git использует индексную копию каждого файла (или BLOB-объекта, в действительности) для создания новогосовершает.Когда вы запускаете git add, Git читает файл рабочего дерева, кодирует его в форму большого двоичного объекта и сохраняет его - ну, на самом деле, его идентификатор хеша - в индексе.Когда вы запускаете git commit, Git просто замораживает копии индекса в подтвержденные копии.

Когда вы запускаете git checkout для переключения на какой-то коммит, Git извлекает фиксацию в индекс (заполняя все хэш-идентификаторы BLOB-объектов), а также извлекает большие двоичные объекты в рабочее дерево, чтобы они были в удобном формате, и вы могли работать с ними.Когда вы запускаете git add, Git сжимает файл рабочего дерева в его формат BLOB-объекта и заменяет индексную запись для файла.

Преобразование BLOB-объекта в файл рабочего дерева или наоборот является идеальнымместо, где Git будет выполнять любые преобразования, которые вам нужны, например, превращение новых строк в окончания строк CRLF.Так что , где Git делает это: git checkout заполняет индекс и расширяет и преобразует в рабочее дерево, а git add сжимает и отменяет преобразование из рабочего дерева в индекс, готов к следующему git commit.(Любые файлы, к которым вы не прикасаетесь, остаются сжатыми и готовы к работе, надежно спрятаны в указателе.)

Выготовы знать, что отслеживаемый файл - это файл, который находится в индексе, а неотслеживаемый файл - это файл, который находится в рабочем дереве, но отсутствует в индексе.Ваша цель - использовать существующие .gitignore, чтобы файлы, находящиеся в данный момент в индексе, удалялись от индекса, если они будут .gitignore -ed.Используемый вами процесс:

  • git rm -r --cached .: удалить все из индекса, чтобы все дерево операций не отслеживалось
  • git add .: создавать все новые BLOB-объекты в индексе из того, что находится в рабочем дереве, игнорируя при этом любой файл, указанный в .gitignore.

Проблема здесь в том, что в рабочем дереве естьбыли преобразованы преобразованиями "blob to work-tree" и будут "не преобразованы" преобразованиями "work-tree to blob".Создание .gitattributes файла с * -text говорит Git: Преобразования, которые нужно сделать, вообще не являются преобразованиями. "

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

Итак, здесь мы используем шаг 1 для создания .gitattributes файла, который говорит: не делать преобразований . Шаг 2, rm .git/index, полностью удаляет индекс. Git теперь понятия не имеет, что на самом деле находится в рабочем дереве. Этот шаг может быть ненужным, но я использую его, чтобы заставить Git действовать на шаге 3, который сообщает Git: извлекает каждый файл из коммита HEAD в индекс и рабочее дерево. Это заново создает индекс и заново заполняет рабочее дерево, на этот раз выполняя no преобразования.

Шаги 4 и 5 такие же, как и раньше, но на этот раз все файлы рабочего дерева совпадают с BLOB-объектами в коммите HEAD, поскольку шаг 3 работал с установленной директивой .gitattributes.6, чтобы убедиться, что вы не фиксируете директиву "не преобразовывать".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...