Как мне зафиксировать только изменения имени файла в Git?

1304

Я изменил имя несколько файлов с помощью де-заглавной буквы, как в Name.jpgк name.jpg. Git не распознает эти изменения, и мне пришлось удалить файлы и загрузить их снова. Есть ли способ, что Git может быть чувствительным к регистру при проверке изменений в именах файлов? Я не вносил никаких изменений в сам файл.

Гил Шульман
источник
4
@ Если это не совсем правильно, Git на самом деле имеет параметр конфигурации, который контролирует, игнорирует ли он регистр чувствительности.
2
возможный дубликат git не чувствителен к регистру?
6
См. Stackoverflow.com/a/24979063/6309 : начиная с git 2.0.1, все работает просто git mv.
VonC
Ссылайтесь на этот пост. Я смог зафиксировать, но просто использовал git commit -m "msg" без каких-либо путей к файлам в качестве параметров. Обновил индекс и проверил в файле. [Ссылка] stackoverflow.com/questions/35790113/…
ARKS

Ответы:

1519

Вы можете использовать git mv :

git mv -f OldFileNameCase newfilenamecase
Кит Смайли
источник
12
это дает мне «исходный каталог пуст», а его нет
WiseStrawberry
6
Использование MacOS здесь (с учетом регистра) и -f работали! Спасибо за совет
Цезарсоль
49
В последних версиях вам больше не нужен -fфлаг.
Джошуа Пинтер
8
Не забудьте указать полный путь к файлу. Очевидно, я знаю, но получил меня на некоторое время
Рикриззо
7
В начале страница проголосовала комментарий: Вы делаете нужен -fкоммутатор с последним мерзавцем (2.18) в противном случае вы можете получить сообщение об fatal: destination existsошибке.
DeepSpace101
1040

Git имеет настройку конфигурации, указывающую его ли быть чувствительны к регистру или нечувствительным: core.ignorecase. Чтобы Git учитывал регистр, просто установите для этого параметра значение false:

git config core.ignorecase false

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

Из git configдокументации :

core.ignorecase

Если true, этот параметр позволяет использовать различные обходные пути, чтобы git работал лучше на файловых системах, не чувствительных к регистру, например, FAT. Например, если распечатка каталога находитmakefile когда ожидает git Makefile, git будет считать, что это действительно тот же файл, и продолжит запоминать его как Makefile.

По умолчанию используется значение false, кроме git-clone (1) или git-init (1). будут проверять и устанавливать значение core.ignorecasetrue, если это необходимо, при создании хранилища.

Нечувствительные к регистру файловые системы

Две самые популярные операционные системы, которые имеют регистронезависимые файловые системы, о которых я знаю, это

  • Windows
  • OS 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
@ Доми, это не ошибка, это ожидаемое поведение. На самом деле это плохая идея установить значение false в нечувствительной файловой системе, потому что это то, что происходит. Причина, по которой git не увидел, что файл в нижнем регистре был удален, заключается в том, что файловая система не сообщает о том, что он был удален, так как игнорирует регистр, в то время как для git эта опция не установлена ​​в false. Дело не в том, что имена файлов не имеют строчных и прописных букв в ntfs или fat, просто поиск файлов игнорирует регистр.
ohcibi
15
@Domi мерзавец является достаточно умны. Вот почему вы не должны устанавливать значение false в файловой системе без учета регистра. Используйте git mvдля перемещения файла и посмотрите, как Git управляет им. Если вы перемещаете файл без git, git ничего не может сделать, поскольку файловая система не говорит правду git. Это проблема ntfs / fat / hfs и тому подобного, а не git / linux.
ohcibi
158

Используя SourceTree, я смог сделать все это из пользовательского интерфейса

  1. Переименовать FILE.ext вwhatever.ext
  2. стадия этот файл
  3. Теперь переименуйте whatever.ext вfile.ext
  4. Поместите этот файл снова

Это немного утомительно, но если вам нужно сделать это только с несколькими файлами, это довольно быстро

CBarr
источник
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 не чувствительна к регистру. Однако у меня
сработало
Использование ФС без учета регистра (на Mac) и -fработало! Спасибо за совет
Цезарсоль
Это также работало с папкой на окнах без -fфлага.
нич
git -c "core.ignorecase=false" add .будет рассматривать файлы, регистр которых был изменен для фиксации.
nietonfir
67

Иногда полезно временно изменить чувствительность к регистру в Git:

Метод № 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 при переходе с строчных на прописные, но не с прописных на строчные. кажется, единственное надежное решение - прекратить использование ОС, которая не распознает регистр имени файла.
aspiringGuru
Есть ли причина, по которой это должно быть временное изменение? Не вызовет ли это проблемы, если я просто оставлю настройки измененными на регистр?
cytsunny
Это может зависеть от нескольких факторов, в частности от того, является ли целевая файловая система чувствительной к регистру - см. En.wikipedia.org/wiki/Case_sensitivity#In_filesystems . Временное изменение может потребоваться, если файловая система развертывания отличается чувствительностью к регистру файловой системы, используемой для разработки. Кроме того, в моем случае я работаю в команде, где все должны иметь одинаковые настройки Git (то есть, чувствительны к регистру), поэтому, если я отключу его, он должен быть временным.
Стив Чемберс
44

В OSX, чтобы избежать этой проблемы и избежать других проблем при разработке в файловой системе без учета регистра, вы можете использовать Дисковую утилиту для создания виртуального диска с учетом регистра. / образа диска с .

Запустите утилиту диска, создайте новый образ диска и используйте следующие параметры (или измените их, как вам угодно, но сохраните их с учетом регистра):

Скриншот Mac Disk Utility

Обязательно сообщите git, что теперь он на регистре чувствительности:

git config core.ignorecase false
user1821510
источник
15
Нет, Nuclear использует загрузочный диск с полным учетом регистра в OSX. Вам придется жить без плохо написанных приложений (например, Adobe) или запускать их на собственной виртуальной машине с глупыми случаями, но это того стоит, если вы пишете в основном для систем * nix.
Майк Маркаччи
1
Это единственный вариант, который правильно работает. Я попробовал все остальное, и вы оказались в том или ином виде. Решите проблему правильно, сделав это.
Джон Хант
2
Обратите внимание, что в Дисковой утилите есть ошибка OS X 10.11 - она ​​не будет создавать чувствительные к регистру изображения. Вам нужно использовать инструмент командной строки hdiutil. apple.stackexchange.com/questions/217915/…
dellsala
7
С APFS в High Sierra это еще проще. Щелкните значок диска со знаком плюс и добавьте том с учетом регистра без ограничений по размеру. Он просто разделяет пространство с основным томом и монтируется в / 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. Выполнено
gmeben
источник
Я переименовал прямо на BitBucket, и это сработало. Спасибо.
RSC
Хорошо знать. Эта техника теоретически должна работать на любой платформе хостинга репозитория, но мне было бы интересно узнать, есть ли такая, с которой она не будет работать.
gmeben
Не работает с файлами, которые нельзя редактировать в браузере, например с изображениями или PDF; нет никакой возможности редактирования, очевидно.
Абхиджит Саркар
@AbhijitSarkar Хороший вопрос. Я обновил свой ответ для этих случаев. Я проверил и подтвердил, что эти инструкции работают.
Gmeben
Кто-нибудь может переименовать каталог таким образом?
Solvitieg
21

Подобно ответу @ Sijmen, это то, что у меня сработало в OSX при переименовании директории (вдохновлено этим ответом из другого поста):

git mv CSS CSS2
git mv CSS2 css

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

PS Кстати, если вы используете Django, collectstatic также не распознает разницу в регистре, и вам придется делать это вручную и в статическом корневом каталоге.

Anupam
источник
19

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

2) зафиксировать удаленный файл Name.jpg

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

4) изменить добавленный файл name.jpgк предыдущему коммиту

git add
git commit --amend
Razon
источник
2
Я получаю это fatal: bad source, source=name1.jpg, destination=name.jpgна шаге 3. У вас есть предложение? Спасибо
Энтони Конг
1
Вы не можете сделать коммит, просто git add.
Alex78191
Выглядит очень бестолково, не так ли? Или исправление обезьян.
Иеромей
18

Я использовал следующие шаги:

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

Для меня это простое решение

andrewvergel
источник
Это решение. И в отличие от других ответов, он работает хорошо, когда вы делаете пакетное переименование. На 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. В Дисковой утилите нажмите кнопку +, когда выбран Контейнерный диск
  2. Выберите APFS (с учетом регистра) в формате
  3. Назови это Sensitive
  4. прибыль
  5. Необязательно: Создайте папку с именем Sensitive 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 moving» файл может быть довольно трудоемким. Итак, что бы я сделал во время моих задач по изменению имени файла:

  1. удалите все не git файлы и папки в другую папку / репозиторий.
  2. зафиксировать текущую пустую папку git (это покажет, как все файлы удалены)
  3. добавьте все файлы обратно в исходную папку / репозиторий git.
  4. зафиксировать текущую непустую папку git.

Это решит все проблемы с делом, не пытаясь выяснить, какие файлы или папки вы переименовали.

Рикардо Виртудазо младший
источник
Почему не git commmit --amendв пункте 4? В противном случае произойдет дополнительная фиксация с удалением всех файлов. Или вы можете использовать git rebase -iс тыквой.
Alex78191
1

Если ничего не работает, используйте git rm filename, чтобы удалить файл с диска и добавить его обратно.

гопал Пандей
источник
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()
пользователь
источник