Редактировать: остающаяся проблема заключается в том, что режимы файлов, по-видимому, неправильно сохраняются в системах 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
, вот шестиступенчатый процесс, который должен работать:
- Создайте этот файл
.gitattributes
так же, как вы это сделали - Выполнить
rm .git/index
- Выполнить
git checkout HEAD -- .
- Выполнить
git rm -r --cached .
- Выполните
git add .
- Выполните
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, чтобы убедиться, что вы не фиксируете директиву "не преобразовывать".