Як зробити фіксацію змін у файлі Git, що відрізняється від регістру?


1300

Я змінив ім'я кілька файлів з допомогою де-великої літери, як в Name.jpgдо name.jpg. Git не розпізнає ці зміни, і мені довелося видалити файли та завантажити їх знову. Чи існує спосіб, коли Git може залежати від регістру під час перевірки змін імен файлів? Я не вніс жодних змін у сам файл.


4
@ якщо це не зовсім правильно, Git насправді має конфігураційне налаштування, яке контролює, чи ігнорує він чутливість до регістру чи ні.


6
Дивіться stackoverflow.com/a/24979063/6309 : оскільки git 2.0.1, простий git mvтвір.
VonC


Перегляньте цю публікацію. Мені вдалося здійснити, але просто використовуючи git commit -m "msg" без будь-яких шляхів до файлів як параметрів. Він оновив індекс і перевірив у файлі. [Посилання] stackoverflow.com/questions/35790113/…
ARKS

Відповіді:


1513

Ви можете використовувати git mv :

git mv -f OldFileNameCase newfilenamecase

12
це дає мені "джерельний каталог порожній", а його немає
WiseStrawberry

6
Використання MacOS тут (нечутливий до регістру FS) та -f працював! Дякую за пораду
цезарсол

49
В останніх версіях -fпрапор вам більше не потрібен .
Джошуа Пінтер

8
Не забудьте дати повний шлях до файлу. Очевидно, я знаю, але
затримав

7
На початку сторінка проголосувала коментар: Ви робите потрібен -fкомутатор з останнім мерзотником (2.18) в іншому випадку ви можете отримати повідомлення про fatal: destination existsпомилку.
DeepSpace101

1035

Git має настройку конфігурації, яка вказує його чи бути чутливі до регістру або нечутливим: core.ignorecase. Щоб визначити, що Git враховує регістр, просто встановіть цей параметр false:

git config core.ignorecase false

Документація

З git configдокументації :

core.ignorecase

Якщо це правда, ця опція дозволяє різним методам вирішення проблем, щоб git краще працював у файлових системах, які не відрізняються від регістру, як FAT. Наприклад, якщо в списку каталогів знайдеться, makefileколи git очікує Makefile, git припустить, що це дійсно той самий файл, і продовжить запам'ятовувати його як Makefile.

Типовим значенням є хибне, за винятком того, що git-clone (1) або git-init (1) буде зондуватися та встановлено core.ignorecasetrue, якщо це доречно, коли створено сховище.

Файлові системи, нечутливі до регістру

Дві найпопулярніші операційні системи, які мають нечутливі до регістру файлові системи, про які я знаю

  • Windows
  • ОС X

9
Зі сторони, я не вважаю, що сам Mac OS X є нечутливим до регістру. Натомість файлова система визначає чутливість до регістру. Форматуючи розділ HFS +, користувачі можуть вибрати, чи зробити його чутливим до регістру чи нечутливим. За замовчуванням не враховує регістр справ.
spaaarky21

225
У цій відповіді здається, що дуже варто відзначити, що встановити цю опцію falseна файлову систему, що не враховує регістр, є поганою ідеєю . Це не обов'язково очевидно. Наприклад, я просто спробував це на своєму Mac, думаючи, що це виправить мої проблеми, а потім перейменував файл з productPageCtrl.jsу ProductPageCtrl.js. git statusпобачив новий файл під назвою, ProductPageCtrl.jsале не думав, що productPageCtrl.jsйого видалено. Коли я додав нові файли, скоєні та натиснуті на GitHub, репортаж GitHub тепер містив обидва файли, хоча моє (нібито до цього часу) місцеве репо було лише одне.
Марк Амері

5
@MarkAmery Це дуже схоже на помилку у вашому клієнті Git. Ви подали звіт?
Домі

24
@Domi це не помилка, це очікувана поведінка. Насправді погана ідея встановити це значення false на нечутливій файловій системі, оскільки саме так і відбувається. Причина, через яку git не бачив, щоб файл малих регістрів був видалений, полягає в тому, що файлова система не повідомляє його про видалений, оскільки він ігнорує випадок, в той час як для цього параметра git не встановлено значення false. Справа не в тому, що назви файлів не мають нижнього та верхнього регістру на ntfs або жирі, саме пошук цього файлу ігнорує випадок.
охцібі

15
@Domi мерзотник є досить розумні. Ось чому ви повинні НЕ встановити це значення БРЕХНЯ на випадок нечутливим файлової системи. Використовуйте git mvдля переміщення файлу і дивіться, як git управляє ним. Якщо ви переміщуєте файл без git, git нічого не може зробити, оскільки файлова система не говорить правду git. Це проблема ntfs / fat / hfs та подібних, а не git / linux.
охцібі

157

Використовуючи SourceTree, я зміг це зробити з інтерфейсу користувача

  1. Перейменувати FILE.ext наwhatever.ext
  2. Поставити цей файл
  3. Тепер перейменуйте whatever.ext наfile.ext
  4. Етап цей файл ще раз

Це трохи нудно, але якщо вам потрібно зробити це лише для кількох файлів, це досить швидко


5
Те саме з git bash
Alex78191

3
"Етап цього файлу" є важливою частиною - жодна з інших відповідей вище не працювала для мене. Він фактично працював із звичайним старим командним рядком Windows.
Влад Сабев

1
Я не усвідомлював, що це спрацьовує через інсценування. Але в моєму випадку я хотів змінити імена папок, а також деякі файли в цих папках. Тому я спочатку перейменував усі папки на тимчасові імена. Введено нові імена (усі файли всередині) та "видалені" файли. Git позначив їх усіх як "перейменованих". Потім перейменовано всі ці папки до їхніх нових версій справи та повторно. Нарешті, об'єднав ці 2 коміти. Але виходячи з того, що ви написали, я міг би зробити все це безпосередньо через зону відпочинку, не створюючи 2 коміти + злиття.
ThermoX

3
Працює також з gitkraken на ім'я папки.
Філіп Матрей

Я написав сценарій Python 3, щоб виконати цю виснажливу роботу: stackoverflow.com/a/58159822/4934640
користувач

126

Це те, що я робив в OS X:

git mv File file.tmp
git mv file.tmp file

Два кроки, оскільки в іншому випадку я отримав помилку "файл існує". Можливо, це можна зробити за один крок, додавши --cachedабо таке.


21
як підказує головна відповідь, -f(сила) - прапор, який ви шукаєте
rperryng

5
@rperryng - ні, -fпрапор не допомагає у випадку, якщо базовий FS є нечутливим до регістру. Однак двоступеневе рішення працювало для мене
HEKTO

Використовуючи нечутливий до регістру FS (на Mac) і -fпрацював! Дякую за пораду
цезарсол

Це також працювало з папкою на Windows без -fпрапора.
nich

git -c "core.ignorecase=false" add .буде розглядати файли, чия справа була змінена для фіксації.
nietonfir

67

Іноді корисно тимчасово змінити чутливість регістру Гіта:

Спосіб №1 - Змінення чутливості регістру для однієї команди:

git -c core.ignorecase=true checkout mybranchщоб вимкнути чутливість регістру для однієї checkoutкоманди. Або в більш загальному плані : . (Подяка VonC за те, що він запропонував це у коментарях.)git -c core.ignorecase= <<true or false>> <<command>>

Спосіб №2 - Змінення чутливості регістру для кількох команд:

Щоб змінити налаштування на довший час (наприклад, якщо перед тим, як змінити його, потрібно виконати кілька команд):

  1. git config core.ignorecase(це повертає поточний параметр, наприклад false).
  2. git config core.ignorecase <<true or false>> - встановити потрібний новий параметр.
  3. ... Запустити кілька інших команд ...
  4. git config core.ignorecase <<false or true>> - встановити значення конфігурації назад до попереднього налаштування.

1
Чому б не прямо git -c core.ignorecase=<true or false> checkout <<branch>>? Нічого після скидання.
VonC

2
У мене був дивний досвід роботи запропонованого core.ignorecase при переході від малого до верхнього регістру, але не для верхнього регістру до малого. Здається, єдиним надійним рішенням є припинення використання ОС, яка не може розпізнати регістр імен файлів.
прагнувГуру

Чи є причина, чому це має бути тимчасова зміна? Чи це спричинить будь-які проблеми, якщо я просто залишу налаштування змінені на регістр?
cytsunny

Це може залежати від кількох факторів, зокрема від того, чи відповідає цільова файлова система регістром - див. En.wikipedia.org/wiki/Case_sensibility#In_filesystems . Тимчасова зміна може знадобитися, якщо файлова система розгортання має різну чутливість регістру до файлової системи, яка використовується для розробки. Також у моєму випадку я працюю в команді, де очікується, що всі мають однакові налаштування Git (тобто залежно від регістру), тому якщо я вимкну його, це має бути тимчасовим.
Стів Чемберс

44

У ОСX, щоб уникнути цієї проблеми та уникнути інших проблем з розвитком файлової системи, нечутливої ​​до регістру, ви можете використовувати Disk Utility для створення віртуального дискового / дискового зображення, залежного від регістру .

Запустіть утиліту диска, створіть нове зображення диска та скористайтеся такими налаштуваннями (або змініть, як вам подобається, але не залежно від регістру):

Скріншот утиліти Mac Disk

Не забудьте сказати git, що він тепер знаходиться на регістрі FS:

git config core.ignorecase false

15
Так, ядерний працює на ОСX, повністю чутливий до регістру. Вам доведеться жити без погано написаних програм (ах, Adobe) або запускати їх у власному випадку, нерозумному VM, але це того варто, якщо ви кодуєте насамперед для * nix систем.
Майк Маркаччі

1
Це єдиний варіант, який правильно працює. Я спробував решту, і ви, в той чи інший спосіб, опиняєтеся солінням. Вирішіть проблему належним чином.
Джон Хант

2
Зауважте, що у програмі Disk Utility є помилка OS X 10.11 - вона не створюватиме регістри зображень. Вам потрібно скористатися інструментом командного рядка hdiutil. apple.stackexchange.com/questions/217915/…
dellsala

7
З APFS у Високій Сьєррі це ще простіше. Клацніть піктограму накопичувача з плюсом і додайте об'ємний регістр, не обмежуючи розмір. Він просто розділяє простір з основним томом і монтується в / Volumes / volume-name.
Майкл Фокс

21

Я спробував наступні рішення з інших відповідей, і вони не спрацювали:

Якщо ваш сховище розміщено віддалено (GitHub, GitLab, BitBucket), ви можете перейменувати файл за початком (GitHub.com) та змусити перейменувати файл зверху вниз.

Наведені нижче інструкції стосуються GitHub, однак загальна ідея, що стоїть за ними, повинна стосуватися будь-якої віддаленої хостингової платформи. Пам’ятайте про тип файлу, який ви намагаєтесь перейменовувати, тобто, чи це тип файлу, який GitHub вважає редагованим (код, текст тощо) або редактором (зображення, двійкові тощо) у веб-переглядачі.

  1. Відвідайте GitHub.com
  2. Перейдіть до вашого сховища на GitHub.com та виберіть філію, в якій працюєте
  3. Використовуючи інструмент навігації файлів сайту, перейдіть до файлу, який ви хочете перейменувати
  4. Чи дозволяє GitHub вам редагувати файл у веб-переглядачі?
    • а.) для редагування
      1. Клацніть піктограму "Редагувати цей файл" (це схоже на олівець)
      2. Змініть ім'я файлу у текстовому вводі назви файлу
    • б.) Непридатні
      1. Відкрийте кнопку «Завантажити» на новій вкладці та збережіть файл на комп’ютері
      2. Перейменуйте завантажений файл
      3. На попередній вкладці на GitHub.com натисніть значок "Видалити цей файл" (схоже на смітник)
      4. Переконайтесь, що branchnameвибрано перемикач "Прив’язати безпосередньо до гілки" та натиснути кнопку "Прийняти зміни"
      5. У цьому ж каталозі на GitHub.com натисніть кнопку "Завантажити файли"
      6. Завантажте перейменований файл зі свого комп’ютера
  5. Переконайтесь, що branchnameвибрано перемикач "Прив’язати безпосередньо до гілки" та натиснути кнопку "Прийняти зміни"
  6. Місцево оформити / забрати / потягнути гілку
  7. Зроблено

Я перейменував безпосередньо на BitBucket, і це спрацювало. Дякую.
rsc

Добре знати. Ця методика теоретично повинна працювати на будь-якій платформі хостингу репозиторію, але мені було б цікаво знати, чи є такі, з якими вона не працюватиме.
gmeben

Не працює для файлів, які не можна редагувати у веб-переглядачі, як-от зображення чи PDF; Очевидно, немає варіанту редагування.
Абхіджіт Саркар

@AbhijitSarkar Добре. Я оновив свою відповідь на ці випадки. Я перевірив і перевірив, як ці інструкції працюють.
gmeben

Хтось вдається перейменувати каталог таким чином?
Солвітіг

20

Подібно до відповіді @ Sijmen, це те, що працювало на мене на OSX під час перейменування каталогу (натхненний цією відповіддю з іншого допису):

git mv CSS CSS2
git mv CSS2 css

Просто це git mv CSS cssпризвело до помилки помилки аргументу: fatal: renaming '/static/CSS' failed: Invalid argumentможливо, тому, що файлова система OSX нечутлива до регістру

ps BTW, якщо ви використовуєте Django, collestatic також не розпізнає різницю регістру, і вам доведеться робити це вище вручну в статичному кореневому каталозі


18

1) перейменувати файл Name.jpgвname1.jpg

2) зробити видалений файл Name.jpg

3) перейменувати файл name1.jpgвname.jpg

4) змінити доданий файл name.jpgдо попереднього комітету

git add
git commit --amend

2
Я отримую це fatal: bad source, source=name1.jpg, destination=name.jpgна кроці 3. Чи є у вас пропозиція? Thx
Ентоні Конг

1
Ви не можете зробити зобов’язання, просто git add.
Alex78191

Виглядає дуже хакі, чи не так? Або мавпочки.
jeromej

18

Я використав ці наступні кроки:

git rm -r --cached .
git add --all .
git commit -a -m "Versioning untracked files"
git push origin master

Для мене це просте рішення


Це рішення. І на відміну від інших відповідей, він добре працює, коли ви робите пакетні перейменування. На glamourphilly.org нам потрібно було змінити кожен .Jpg на .jpg. У Finder ви можете робити такі перейменування, і ця відповідь дозволяє вам перевірити це.
Вільям Ентрікен

11

Ми можемо використовувати команду git mv. Приклад нижче, якщо ми перейменували файл abcDEF.js на abcdef.js, ми можемо запустити наступну команду з терміналу

git mv -f .\abcDEF.js  .\abcdef.js

8

Mac OSX High Sierra 10.13 виправляє це дещо. Просто зробіть віртуальний розділ APFS для своїх git-проектів, за замовчуванням він не має обмеження розміру і не займає місця.

  1. У програмі Disk Utility натисніть кнопку + під час вибору диска Container
  2. Виберіть APFS (залежно від регістру) у форматі
  3. Назвіть це Sensitive
  4. Прибуток
  5. Необов’язково: Створіть папку в чутливих викликаних gitіln -s /Volumes/Sensitive/git /Users/johndoe/git

Ваш привід буде в /Volumes/Sensitive/

введіть тут опис зображення

Як зробити фіксацію змін у файлі Git, що відрізняється від регістру?


Мені подобається ця пропозиція, вона елегантно і безболісно вирішує проблему, не вдаючись до некрасивих способів вирішення проблеми. Дякую!
Філ Глігхорн

4

Я кілька разів стикався з цією проблемою на MacOS. Git чутливий до регістру, але Mac зберігає лише регістр.

Хтось робить файл: Foobar.javaі через кілька днів вирішує перейменувати його в FooBar.java. Коли ви витягуєте останній код, він не вдаєтьсяThe following untracked working tree files would be overwritten by checkout...

Єдиний надійний спосіб, який я бачив, це виправляє:

  1. git rm Foobar.java
  2. Зверніть це повідомлення, яке ви не можете пропустити git commit -m 'TEMP COMMIT!!'
  3. Потягніть
  4. Це з'явиться конфлікт, який змусить вас об'єднати конфлікт - оскільки ваша зміна його видалила, а інша зміна перейменована (звідси проблема)
    1. Прийміть вашу зміну, яка є "видаленням"
    2. git rebase --continue
  5. Тепер опустіть обхідний шлях git rebase -i HEAD~2іdropTEMP COMMIT!!
  6. Переконайтеся, що файл тепер викликається FooBar.java

3

Коли ви зробили багато перейменувань файлів і деякі з них - це лише зміна корпусу, важко запам'ятати, що це таке. вручну "переміщення git" файлу може бути певною роботою. Отож, що я б робив під час завдань щодо зміни імені файлу:

  1. видаліть усі файли та папки non-git до іншої папки / сховища.
  2. ввести поточну порожню папку git (це відображатиметься як видалені всі файли.)
  3. додати всі файли назад в оригінальну папку / сховище git.
  4. зробити поточну не порожню папку git.

Це дозволить виправити всі випадки справи, не намагаючись з’ясувати, які файли чи папки ви перейменували.


Чому б не git commmit --amendу пункті 4? Інакше буде додаткова комісія з видаленням усіх файлів. Або можна використовувати git rebase -iз кабачком.
Alex78191

1

Якщо нічого не вийшло, використовуйте ім'я файлу git rm, щоб видалити файл з диска та додати його назад.


0

Я взяв відповідь @CBarr і написав сценарій Python 3, щоб зробити це зі списком файлів:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import os
import shlex
import subprocess

def run_command(absolute_path, command_name):
    print( "Running", command_name, absolute_path )

    command = shlex.split( command_name )
    command_line_interface = subprocess.Popen( 
          command, stdout=subprocess.PIPE, cwd=absolute_path )

    output = command_line_interface.communicate()[0]
    print( output )

    if command_line_interface.returncode != 0:
        raise RuntimeError( "A process exited with the error '%s'..." % ( 
              command_line_interface.returncode ) )

def main():
    FILENAMES_MAPPING = \
    [
        (r"F:\\SublimeText\\Data", r"README.MD", r"README.md"),
        (r"F:\\SublimeText\\Data\\Packages\\Alignment", r"readme.md", r"README.md"),
        (r"F:\\SublimeText\\Data\\Packages\\AmxxEditor", r"README.MD", r"README.md"),
    ]

    for absolute_path, oldname, newname in FILENAMES_MAPPING:
        run_command( absolute_path, "git mv '%s' '%s1'" % ( oldname, newname ) )
        run_command( absolute_path, "git add '%s1'" % ( newname ) )
        run_command( absolute_path, 
             "git commit -m 'Normalized the \'%s\' with case-sensitive name'" % (
              newname ) )

        run_command( absolute_path, "git mv '%s1' '%s'" % ( newname, newname ) )
        run_command( absolute_path, "git add '%s'" % ( newname ) )
        run_command( absolute_path, "git commit --amend --no-edit" )

if __name__ == "__main__":
    main()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.