Расхождение в капитализации между локальным и удаленным - PullRequest
2 голосов
/ 13 марта 2020

В проекте Git / GiHub у меня было несколько файлов с именами, где все аббревиатуры были заглавными. Например:

ПЕБКА C. js:

export const PEBKAC = ...

прочее. js:

import { PEBKAC } from './PEBKAC'

Я решил, что заглавные буквы из длинных сокращений был визуально непривлекательным и переименовал файл в моем редакторе (VSCode, на MacOS) и объект в:

Pebka c. js:

export const pebkac = ...

прочее. js :

import { pebkac } from './Pebkac'

Я зафиксировал изменение и заметил, что файл PEBKAC.js был помечен как «измененный», а не «переименован», но я тем не менее зафиксировал и нажал.

Сейчас просматривая файл в GitHub, я вижу его как PEBKAC.js, который не будет работать из-за импорта, в то время как локально я вижу его как Pebkac.js. Git не видит разницы между удаленным и локальным. Как произошло это несоответствие и как я могу это исправить?


Проблема решена, подробности см. В принятом ответе. Решение:

git mv PEBKAC.js Pebkac.js

1 Ответ

2 голосов
/ 13 марта 2020

Вы на самом деле не переименовывали файлы. Ну, ты сделал, но ты не сделал. Подождите, это может сбить с толку.

Git на самом деле не работает с файлами, не совсем так, как ваш компьютер в любом случае. Git работает с коммитами , а git push отправляет коммиты. GitHub поэтому имеет нет файлов на нем; он просто имеет коммиты.

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

Git еще больше усложняет это: на вашем компьютере, сначала Git извлекает коммит в Git s index . Индекс на самом деле является файлом данных. Он содержит имена файлов, но не в той форме, которую использует ваш компьютер. Например, файл с именем dir/sub/file.ext буквально просто хранится как dir/sub/file.ext в индексе. Ваш компьютер требует, чтобы Git создал папку / каталог с именем dir, затем внутри него создайте папку с именем sub, а затем внутри нее создайте file.ext, так что есть файл с именем file.ext в папке с именем sub в папке с именем dir. (Вы можете назвать это dir\sub\file.ext, даже.) Но в index это просто файл с именем dir/sub/file.ext.

Имена файлов в индексе учитывается регистр и используются прямые косые черты (всегда, даже на Windows).

Имена файлов на вашем компьютере , сохраненные в папках, по крайней мере на ваш компьютер; некоторые отличаются - не регистрозависимо. То есть, когда существует dir\sub\file.ext, использование DIR\suB\fIlE.ExT обращается к тому же файлу. Поэтому не имеет значения, если вы измените регистр этих файлов на диске, потому что на вашем компьютере file.ext, File.ext и FILE.EXT - это все один и тот же файл.

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

Если вы используете git mv, вы может получить Git для обновления индексной копии имени файла (при этом также обновляя имя файла в файловой системе). Это может потребовать относительно современного Git; некоторые более старые версии Git менее способны.

Например, на моем Ma c (который использует косую черту, но по умолчанию используется файловая система без учета регистра):

sh-3.2$ ls
File.Ext        README.md
sh-3.2$ mv File.Ext file.ext
sh-3.2$ ls
README.md       file.ext
sh-3.2$ git status
On branch master
nothing to commit, working tree clean

Обратите внимание на отсутствие переименования. Но сейчас:

sh-3.2$ git mv File.Ext file.ext
sh-3.2$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        renamed:    File.Ext -> file.ext

(Git на моей Ma c для тестирования здесь немного устарел, 2.20.1, но это явно поздно, чтобы заставить git mv работать правильно. )

Когда вы делаете new commit, Git использует то, что находится в индексе, а не то, что находится в рабочем дереве. Если файлы в index имеют имена в старом регистре, новый коммит также будет иметь имена в старом регистре.

Не всегда легко увидеть, что находится в индексе - git status умышленно сокращает вывод, показывая вам, что отличается , а не от того, что там есть - и если вы сделаете это в большом проекте, он напечатает слишком много данных, но, чтобы посмотрите, что находится в индексе, в его относительно сырой форме, используйте git ls-files --stage:

sh-3.2$ git ls-files --stage
100644 5f6a92a7cb8dec274ebbd7a471ba4101766336ab 0       README.md
100644 d2b181532c33ab30ff5396341da30a7ef162a1d6 0       file.ext

Самое левое поле - это mode файла, следующее поле - blob ha sh, 1 третье поле (которое всегда будет нулевым, если вы не находитесь в середине конфликтующего слияния) - это число "промежуточной ячейки", а последнее поле - имя файла, завершенное прямой косой чертой (но ни одна из них не имеет косой черты в них, так что это на самом деле не показывает его, плюс MacOS в любом случае использует forward sla * sh).

Итак:

Теперь на Github существуют файлы со старой заглавной буквы ...

* 109 6 *

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

То, что вы увидите, зависит от того, как вы выглядите: если вы посмотрите в рабочее дерево ( рабочая область на вашем компьютере), ваш компьютер может делать сгибы, вызывая интересную ложь. 2 Если вы посмотрите на index , вы увидите Git истину как извлечено из коммита. Если вы используете веб-браузер GitHub, вы увидите, что через ваш браузер отфильтрована правда (которая может скрывать некоторые вещи).


1 blob ha sh определяется содержимым файла: Git не сохраняет фактические данные файла непосредственно в индексе, а создает или повторно использует один из его внутренних объектов BLOB-объектов для хранения содержимого файла , Таким образом, каждый раз, когда вы фиксируете тот же контент, что и в любом другом файле, хранящемся в любом другом коммите, Git может просто повторно использовать существующего файла только для внутреннего использования в замороженном формате. Что входит в индекс и, следовательно, входит в каждый последующий коммит, это режим, имя пути и блоб ha sh.

2 На Ma c, имена файлов хранятся в NFD, что может помешать использованию файла с именем schön или agréable, который был впервые создан на Linux, который просто хранит необработанные байты UTF-8, как бы вы их ни записывали. Подробнее см. в этом сообщении Супер пользователя .

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