Git: невозможно создать символическую ссылку (имя файла слишком длинное)

Я перенес проект из Linux в Bitbucket, а затем клонировал его в Windows. Оказалось, что были две символические ссылки, которые появились в Windows как текстовые файлы. Поскольку я знал, куда они должны указывать, я заменил их копиями файлов назначения, зафиксировал и отправил.

Теперь репозиторий Bitbucket выглядит нормально, когда я смотрю на него через их веб-интерфейс. Однако git clone на моей Unix-машине дает мне два сообщения вроде:

error: unable to create symlink ... (File name too long)

и два файла, которые ранее были символическими ссылками, отсутствуют. Я попытался клонировать в /tmp/..., чтобы получить более короткие имена файлов, но получил те же результаты. Это говорит о том, что что-то пошло не так с репозиторием Bitbucket. Я пробовал core.symlinks и выключал.

Я могу жить без символических ссылок, но я хотел бы иметь рабочий репозиторий. Кто-нибудь знает способ (кроме воссоздания хранилища)?

Ответы

Ответ 1

Как только вы изменили содержимое файла fake-symlink без изменения его режима с символической ссылки на обычный файл и зафиксировали результат, вы сделали blob, который невозможно извлечь в ОС с настоящими символическими ссылками, потому что у вас есть объект, который должен быть символической ссылкой, но его содержимое слишком длинное, чтобы быть именем пути. Веб-интерфейс не делает вам никаких выгод, скрывая эту проблему.

Вам, вероятно, придется выполнить резервное копирование, чтобы зафиксировать его, исправить и повторно передать все после него. git rebase -i поможет, но это все равно может быть нелегко, особенно если вы внесли больше изменений в файлы, когда они находились в этом фиктивном состоянии symlink-but-not-really-a-symlink.

Предположим, что bad commit abcdef123, вам нужно сделать это:

git rebase -i 'abcdef123^'

который поместит вас в редактор со списком коммитов. abcdef123 должен находиться в первой строке. В этой строке измените pick на edit. Если есть более одного плохого коммита, измените их все на edit. Сохраните и выйдите из редактора.

Теперь вы вернетесь в момент, когда вы совершили плохой файл. Это ваш шанс изменить историю, приложив все к чему, когда-то пошло не так. Осмотрите фиксацию с помощью

git show

и отмените неудачную часть, восстановив исходный путь symlink в файле и git add. Или вы действительно можете избавиться от symlink правильно с помощью git rm, а затем создать новый файл и git add, что. Если вы выберете первый вариант, имейте в виду, что содержимое символической ссылки - это просто путь. Это не текстовый файл - он не имеет новой строки в конце. Если вы отредактируете его с помощью текстового редактора, который добавит новую строку, у вас будет сломанная символическая ссылка (указывающая на файл с новой строкой в ​​его имени).

После того, как вы выполнили свой git add, вставьте фиксированную фиксацию в свое место в истории:

git commit --amend
git rebase --continue

Если вы изменили несколько коммитов от pick до edit, вам придется повторить эту процедуру для каждого из них. Окончательный git rebase --continue вернет вас к настоящему.

Если вы участвуете в прошлой фиксации во время rebase, и вы обнаруживаете, что вся фиксация плохая (она не сделала ничего другого, кроме замены символической ссылки на немодифицированный контент файла, на который она указывает), тогда вы можете git rebase --skip вместо о внесении изменений и продолжении. Если вы заранее знаете, что это произойдет, вы можете просто удалить плохое коммит из списка git rebase -i вместо изменения pick на edit.

Если у вас несколько ветвей, затронутых плохим фиксатором (-ами), вам придется повторить всю процедуру для каждой ветки. Проверьте ветвь, запустите git rebase -i до завершения (когда git rebase --continue говорит "Успешно переустановлено" ), затем проверьте следующую ветку и повторите ее.

В будущем, когда вы раскалываете свою разработку между Windows и реальной ОС, работайте в Windows с cygwin. Внутри cygwin символические ссылки являются символическими ссылками, и вы не можете их испортить, как и вы.

Ответ 2

Вот решение, которое не требует от вас возврата и исправления. В конце концов, это может быть нецелесообразно, если репо является удаленным или общим. Он использует core.symlinks = false. Вы сказали, что попробовали это, но не сказали, когда. Вы должны сделать это до проверки, которую по умолчанию делает обычный клон. Таким образом, вы должны клонировать с опцией -no-checkout.

git clone --no-checkout the-repo tmp-clone-dir
cd tmp-clone-dir
git config core.symlinks false
git checkout
cp the-problem-file the-problem-file.bak # make a backup
git rm the-problem-file
git commit -m 'Removed problem file pretending to be a symlink' the-problem-file
mv the-problem-file.bak the-problem-file # restore the backup; now it will be of type file
git commit -m 'Added back the problem file - now with the correct type' the-problem-file
git push origin master
cd ..
\rm -rf tmp-clone-dir  # IMPORTANT

Этот последний шаг важен, потому что вы не хотите больше работать в репо с помощью core.symlinks = false. Он просто просит неприятностей.

Вышеупомянутое предполагает, что вы хотите, чтобы файл был файлом, а не символической ссылкой. Если бы это означало символическую ссылку, то вы остановились бы после первого фиксации, удалили tmp-clone-dir и вернулись к своей обычной проверке репо, чтобы сделать символическую ссылку и зафиксировать ее.

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

Ответ 3

У меня была эта проблема, это разрешило это для меня:

git config core.symlinks false
git rm <problem-file>
git commit <problem-file>
git push
git config core.symlinks true

Ответ 4

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

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

Ответ 5

У меня была такая же проблема с небольшим количеством файлов. Я решил это, удалив их из репозитория с помощью git remove --cached <file> который не удаляет файлы в моем источнике (которые больше не являются символическими ссылками). Когда все они удалены, git видит, что они все еще там, поэтому я могу добавить их обратно, используя git add. и затем передайте их обратно. Теперь git видит их как обычные файлы.