Ветви GitHub: проблема чувствительности к регистру? - PullRequest
2 голосов
/ 07 марта 2019

Кажется, у меня проблема с хранилищем, постоянно воссоздающим ветки локально из-за некоторых удаленных веток. Я на машине с Windows, поэтому подозреваю, что это проблема чувствительности к регистру.

Вот пример пары команд:

$ git pull
From https://github.com/{my-repo}
 * [new branch]          Abc -> origin/Abc
 * [new branch]          Def -> origin/Def
Already up to date.

$ git pull -p
From https://github.com/{my-repo}
 - [deleted]             (none)     -> origin/abc
 - [deleted]             (none)     -> origin/def
 * [new branch]          Abc -> origin/Abc
 * [new branch]          Def -> origin/Def
Already up to date.

При выполнении git pull соответствующие ветви пишутся с большой буквы. Когда я делаю git pull -p (для сокращения), он сначала пытается удалить версии ветвей в нижнем регистре, а затем создает заглавные версии.

Удаленные ветви пишутся с большой буквы (origin/Abc и origin/Def).

Я попытался временно изменить конфигурацию Git так, чтобы ignorecase=false (в настоящее время ignorecase=true). Но я не заметил никаких изменений в поведении. Я предполагаю, что есть что-то локальное с моей стороны, которое в настоящее время держится за эти ветви в нижнем регистре. Но git branch не показывает ни одной версии этих веток локально.

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

Ответы [ 3 ]

2 голосов
/ 08 марта 2019

Git по этому поводу шизофреничен. 1 Части Git чувствительны к , поэтому ветвь HELLO и ветвь hello разные ветки,Другие части Git в Windows и MacOS в любом случае чувствительны к регистру в , так что ветвь HELLO и ветвь hello совпадают с ветвью.

Результатом является путаница.Эту ситуацию лучше всего просто полностью избежать.

Чтобы исправить проблему:

  1. Задайте дополнительные , частные и временные, имя ветви или тега (s) что вас не смущает запоминание любых хеш-идентификаторов коммитов, которые вас действительно волнуют, в вашем локальном репозитории.Затем запустите git pack-refs --all, чтобы все ваши ссылки были упакованы.Это удаляет все имена файлов , помещая все ваши ссылки в плоский файл .git/packed-refs, где их имена чувствительны к регистру.Теперь ваш Git может отличить ваш Abc от вашего abc, если у вас есть оба.

    Теперь, когда ваш репозиторий не запутан, удалите любые плохие имена веток.Ваши временные имена содержат значения, которые вы хотите запомнить.Вы можете удалить оба abc и Abc, если один или оба могут быть испорчены.Ваш remember-abc содержит правильный хэш.

  2. Перейдите на сервер Linux, на котором есть ветви, отличающиеся только вашим регистром.(Это всегда Linux-машина; эта проблема никогда не возникает на серверах Windows или MacOS, потому что они выполняют свертывание регистраций настолько рано, что вы никогда не создаете проблему в первую очередь.) Там переименуйте или удалите оскорбительного пользователяплохие имена.

    У машины Linux нет проблем с регистром - ветви, имена которых отличаются только регистром, всегда разные - поэтому здесь нет ничего странного.Это может занять несколько шагов и несколько команд git branch, чтобы перечислить все имена, но в конечном итоге у вас не останется ничего, кроме четких и отличных имен: не будет ветвей с именами Abc и abc оба.

    Если на сервере Linux таких проблем нет, выполните шаг 2 «ничего не делать».

  3. Используйте git fetch --prune в локальной системе.Теперь у вас больше нет плохих имен в качестве имен для удаленного отслеживания, потому что на шаге 2 вы убедились, что сервер - система, которую ваш локальный Git называет origin - не имеет плохих имен, и ваш локальный Git сделал ваш локальный origin/* имена соответствуют их именам ветвей.

  4. Теперь заново создайте любые имена веток, которые вы хотите локально, и / или переименуйте временные имена, которые вы сделали на шаге 1. Например, если вы сделали remember-abc чтобы запомнить abc, вы можете просто запустить git branch -m remember-abc abc до и переместить remember-abc в abc.

    Если abc должен иметь origin/abc в качестве восходящего потока, сделайте это сейчас:

    git branch --set-upstream-to=origin/abc abc
    

    (Вы можете сделать это на шаге 1, когда создаете remember-abc, но я думаю, что это имеет больше смысла, поэтому я поместил его на шаг 4.)

Существуют различные сочетания клавиш, которые можно использовать вместо 4 шагов, описанных выше.Я перечислил все четыре способа для ясности цели: для вас должно быть очевидно, что каждый шаг предназначен для выполнения , и, если вы прочитаете остальную часть этого, почему вы делаетеэтот шаг.

Причина возникновения проблемы описана в nowox's answer : Git иногда сохраняет имя ветки в имени файла, а иногда сохраняет его в виде строки в файле данных.Поскольку Windows (и MacOS) склонны использовать сопоставление имен файлов, вариант имени файла сохраняет свой первоначальный регистр, но игнорирует попытки создать второй файл с другим именем варианта варианта, и тогда Git считает, что Abc иabc иначе одинаковы .Вариант data-in-a-file сохраняет различие в регистре, а также различие в значениях и считает, что Abc и abc - это две разные ветви, которые идентифицируют две разные фиксации.

Whru git rev-parse refs/heads/abc или git rev-parse refs/remotes/origin/abc получает информацию из .git/packed-refs - файла данных, содержащего строки - он получает "правильную" информацию. Но когда он получает информацию из файловой системы, попытка открыть .git/refs/heads/abc или .git/refs/remotes/origin/abc фактически открывает .git/refs/heads/Abc (если этот файл существует прямо сейчас) или вариант удаленного отслеживания с аналогичным названием (если этот файл существует) и Git получает «неправильную» информацию.

Установка core.ignorecase (на что угодно) совсем не помогает, так как это влияет только на на то, как Git обрабатывает свертывание регистра в рабочем дереве . Файлы внутри внутренних баз данных Git никак не затрагиваются.

Вся эта проблема никогда бы не возникла, если бы, например, Git использовал реальную базу данных для хранения своей таблицы . Использование отдельных файлов прекрасно работает в Linux. Он не работает нормально на Windows и MacOS, так или иначе. Использование отдельных файлов может работать там , если Git не хранит их в файлах с читаемыми именами - например, вместо refs/heads/master, возможно, Git может использовать файл с именем refs/heads/6d6173746572 хотя это вдвое сокращает доступную длину имени компонента. (Упражнение: как 0x6d m, 0x61 a и т. Д.?)


1 Технически, это неправильное слово. Это конечно описательно, хотя. Лучшее слово может быть шизоид , как оно используется в названии одного эпизода "Узник" , но оно также имеет неверное значение. Коренное слово здесь на самом деле раскол , означающее раскол и несколько противоположность, и вот к чему мы клоним.

2 голосов
/ 08 марта 2019

В Git ветви - это просто указатели на коммит. Ветви хранятся в виде простых файлов в вашем .git хранилище.

Например, у вас могут быть abc и def файлы на .git/refs/heads.

$ tree .git/refs/heads/
.git/refs/heads/
├── abc
├── def
└── master

Содержимое этих файлов - это просто номер коммита, на который указывает ветка.

Я не уверен, но я думаю, что опция ignorecase относится только к вашему рабочему каталогу, а не к папке .git. Таким образом, чтобы удалить странные заглавные ветви, вам может потребоваться просто удалить / переименовать файлы в .git/refs/heads.

В дополнение к этому в файле .git/config хранится обратная связь от локальной ветки к удаленной ветке. В этом файле у вас может быть что-то вроде:

[branch "Abc"]
        remote = origin
        merge = refs/heads/abc

Обратите внимание, что в этом примере удаленная ветвь имеет имя Abc, а локальная ветвь - abc (строчные буквы).

Чтобы решить вашу проблему, я бы попробовал:

  1. Изменить .git/config файл
  2. Переименовать поврежденные ветви в .git/refs/heads, например abc переименовано abc-old
  3. Попробуй git pull
1 голос
/ 08 марта 2019

Ответы, предоставленные nowox и torek , были очень полезными, но не содержали точного решения. Существующие ссылки на remote в .git/config и файлы в git/refs/heads не содержат версий abc или def.

Вместо этого проблема существовала в .git/refs/remotes/origin.

В каталоге

My .git/refs/remotes/origin были ссылки на строчные версии этих папок ветви функций. Некоторые ветви функций были созданы в abc и def с использованием версий в нижнем регистре, но они больше не существуют на удаленном компьютере. Создатель этих ветвей функций недавно переключился на использование Abc и Def на пульте. Я удалил .git/refs/remotes/origin/abc и .git/refs/remotes/origin/def, затем выполнил свежие команды git pull -p. Новые папки, Abc и Def, были созданы, а последующие pull s или fetch es правильно отображают Already up to date.

Спасибо nowox и torek за то, что я выбрал правильный путь!

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