Jak zatwierdzić zmiany nazw plików z rozróżnianiem wielkości liter w Git?

1300

Zmieniłem nazwy kilku plików przez de pierwszą literę, jak w Name.jpgdo name.jpg. Git nie rozpoznaje tych zmian i musiałem usunąć pliki i przesłać je ponownie. Czy istnieje sposób, aby Git rozróżniał wielkość liter podczas sprawdzania zmian w nazwach plików? Nie dokonałem żadnych zmian w samym pliku.

Gil Shulman
źródło
4
@nif to nie jest całkiem poprawne, Git faktycznie ma ustawienie konfiguracji, które kontroluje, czy ignoruje wielkość liter.
6
Zobacz stackoverflow.com/a/24979063/6309 : od wersji git 2.0.1 prosta git mvpraca.
VonC
możliwy duplikat Git: zmiana wielkich liter nazw plików
KyleMit
Zobacz ten post. Byłem w stanie dokonać zatwierdzenia, ale po prostu użyłem git commit -m "msg" bez żadnych ścieżek plików jako parametrów. Zaktualizował indeks i zapisał w pliku. [Link] stackoverflow.com/questions/35790113/…
ARKS

Odpowiedzi:

1513

Możesz użyć git mv :

git mv -f OldFileNameCase newfilenamecase
Keith Smiley
źródło
12
daje mi to „katalog źródłowy jest pusty”, a nie jest
WiseStrawberry
6
Używanie MacOS tutaj (FS bez rozróżniania wielkości liter) i -f działało! Dzięki za podpowiedź
caesarsol
49
W najnowszych wersjach -fflaga nie jest już potrzebna .
Joshua Pinter
8
Nie zapomnij podać pełnej ścieżki pliku. Oczywiście, wiem, ale dostałem na jakiś czas
rickrizzo
7
Na górę głosowali komentarz: ty zrobić potrzebujemy -fprzełącznik z najnowszych git (2,18), w przeciwnym razie można dostać się fatal: destination existsbłąd.
DeepSpace101
1035

Git posiada ustawienia konfiguracyjnego, który mówi to, czy chce być wielkość liter lub niewrażliwe: core.ignorecase. Aby powiedzieć Gitowi, aby rozróżniał wielkość liter, po prostu ustaw to ustawienie na false:

git config core.ignorecase false

Dokumentacja

Z git configdokumentacji :

core.ignorecase

Jeśli to prawda, ta opcja umożliwia różne obejścia, aby git działał lepiej w systemach plików, które nie rozróżniają wielkości liter, takich jak FAT. Na przykład, jeśli lista katalogów znajdzie się, makefilegdy git się spodziewa Makefile, git przyjmie, że jest to naprawdę ten sam plik, i będzie go nadal zapamiętywał jako Makefile.

Wartość domyślna to false, z wyjątkiem tego, że git-clone (1) lub git-init (1) sondują i ustawią wartość core.ignorecasetrue, jeśli to właściwe, podczas tworzenia repozytorium.

Systemy plików bez rozróżniania wielkości liter

Są dwa najpopularniejsze systemy operacyjne, w których nie są rozróżniane małe i wielkie litery

  • Windows
  • OS X

źródło
9
Na marginesie, nie sądzę, że sam Mac OS X nie rozróżnia wielkości liter. Zamiast tego to system plików określa wielkość liter. Podczas formatowania partycji HFS + użytkownicy mogą zdecydować, czy wielkość liter ma być uwzględniana, czy nie. Wielkość liter nie uwzględnia wielkości liter.
spaaarky21,
225
W tej odpowiedzi wydaje się bardzo warte odnotowania, że ​​ustawienie tej opcji falsew systemie plików bez rozróżniania wielkości liter jest złym pomysłem . To niekoniecznie jest oczywiste. Na przykład po prostu wypróbowałem to na komputerze Mac, myśląc, że to rozwiąże moje problemy, a następnie zmieniłem nazwę pliku z productPageCtrl.jsna ProductPageCtrl.js. git statuszobaczyłem nowy plik o nazwie, ProductPageCtrl.jsale nie sądziłem, że productPageCtrl.jszostał usunięty. Kiedy dodałem nowe pliki, zatwierdziłem i przekazałem do GitHub, repozytorium GitHub zawierało teraz oba pliki, chociaż moje (podobno aktualne) repozytorium lokalne miało tylko jeden.
Mark Amery
5
@MarkAmery To brzmi jak błąd w Twoim kliencie Git. Czy złożyłeś raport?
Domi
24
@Domi to nie jest błąd, jest to oczekiwane zachowanie. W rzeczywistości złym pomysłem jest ustawienie tego na false w niewrażliwym systemie plików, ponieważ tak się dzieje. Powodem, dla którego git nie widział usuniętego pliku z małymi literami, jest to, że system plików nie zgłasza go jako usunięty, ponieważ ignoruje sprawę, podczas gdy git nie ma tej opcji ustawionej na false. To nie jest tak, że nazwy plików nie mają małych lub wielkich liter w NTFS ani nie są grubsze, tylko wyszukiwanie nazw plików ignoruje wielkość liter.
ohcibi
15
@Domi git jest wystarczająco inteligentny. To dlatego należy nie ustawione na false w przypadku niewrażliwego systemu plików. Użyj, git mvaby przenieść plik i zobaczyć, jak git nim zarządza. Jeśli przenosisz plik bez git, nic nie może zrobić, ponieważ system plików nie mówi prawdy do git. Jest to kwestia ntfs / fat / hfs i tym podobnych, a nie git / linux.
ohcibi
157

Dzięki SourceTree mogłem to wszystko zrobić z interfejsu użytkownika

  1. Zmień nazwę FILE.ext nawhatever.ext
  2. Wykonaj ten plik
  3. Teraz zmień nazwę whatever.ext nafile.ext
  4. Wykonaj ponownie ten plik

Jest to trochę żmudne, ale jeśli musisz zrobić to tylko z kilkoma plikami, jest to dość szybkie

CBarr
źródło
5
To samo z git bash
Alex78191
3
„Etap ten plik” jest ważną częścią - żadna z powyższych odpowiedzi nie działała dla mnie. To faktycznie działało ze zwykłym starym wierszem poleceń systemu Windows.
Vlad Sabev,
1
Nie zdawałem sobie sprawy, że to działało w strefie przeciwności. Ale w moim przypadku chciałem zmodyfikować nazwy folderów, a także niektóre pliki w tych folderach. Najpierw zmieniłem nazwy wszystkich folderów na nazwy tymczasowe. Zatwierdzono nowe nazwy (wszystkie pliki) i pliki „usunięte”. Git oznaczył je wszystkie jako „przemianowane”. Następnie przemianowano wszystkie te foldery z powrotem na nowe wersje skrzynek i zatwierdzono ponownie. Na koniec połączyłem te 2 zobowiązania. Ale w oparciu o to, co napisałeś, mogłem zrobić to wszystko bezpośrednio przez obszar sating, bez tworzenia 2 zatwierdzeń + scalenia.
ThermoX,
3
Działa również z gitkraken w nazwie folderu.
Philippe Matray
Napisałem skrypt Pythona 3, aby wykonać tę żmudną pracę: stackoverflow.com/a/58159822/4934640
użytkownik
126

Oto co zrobiłem na OS X:

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

Dwa kroki, ponieważ w przeciwnym razie pojawia się błąd „istnieje plik”. Być może można to zrobić w jednym kroku, dodając --cachedlub coś takiego.

Sijmen Mulder
źródło
21
jak sugeruje najwyższa odpowiedź, -f(force) to flaga, której szukasz
rperryng
5
@rperryng - nie, -fflaga nie pomaga w przypadku, gdy FS nie uwzględnia wielkości liter. Jednak dwuetapowe rozwiązanie zadziałało dla mnie
HEKTO
Używanie FS bez rozróżniania wielkości liter (na Macu) i -fdziałało! Dzięki za wskazówkę
caesarsol,
Działa to również z folderem w systemie Windows bez -fflagi.
nich
git -c "core.ignorecase=false" add .rozważy pliki, których wielkość liter została zmieniona w celu zatwierdzenia.
nietonfir
67

Czasami przydaje się tymczasowa zmiana wielkości liter w Git:

Metoda nr 1 - Zmień rozróżnianie wielkości liter dla pojedynczego polecenia:

git -c core.ignorecase=true checkout mybranchaby wyłączyć rozróżnianie wielkości liter dla pojedynczego checkoutpolecenia. Lub bardziej ogólnie:git -c core.ignorecase= <<true or false>> <<command>> . (Podziękowania dla VonC za zasugerowanie tego w komentarzach).

Metoda nr 2 - Zmień rozróżnianie wielkości liter dla wielu poleceń:

Aby zmienić ustawienie na dłużej (np. Jeśli przed ponowną zmianą należy uruchomić wiele poleceń):

  1. git config core.ignorecase (zwraca bieżące ustawienie, np false .).
  2. git config core.ignorecase <<true or false>> - ustaw żądane nowe ustawienie.
  3. ... Uruchom wiele innych poleceń ...
  4. git config core.ignorecase <<false or true>> - przywróć wartość konfiguracji do poprzedniego ustawienia.
Steve Chambers
źródło
1
Dlaczego nie bezpośrednio git -c core.ignorecase=<true or false> checkout <<branch>>? Nic po tym nie można zresetować.
VonC
2
Miałem dziwne doświadczenie z proponowanym core.ignorecase działającym przy zmianie małych liter na wielkie, ale nie dla wielkich liter na małe. wydaje się, że jedynym niezawodnym rozwiązaniem jest zaprzestanie używania systemu operacyjnego, który nie rozpoznaje wielkości liter w nazwie pliku.
aspirującyGuru
Czy istnieje powód, dla którego powinna to być tymczasowa zmiana? Czy spowodowałoby to jakikolwiek problem, jeśli po prostu zmienię ustawienia na wielkość liter?
cytsunny
Może to zależeć od kilku czynników, w szczególności od tego, czy w docelowym systemie plików rozróżniana jest wielkość liter - patrz en.wikipedia.org/wiki/Case_sensitivity#In_filesystems . Tymczasowa zmiana może być potrzebna, jeśli system plików wdrażania ma różną wielkość liter w stosunku do systemu plików używanego do programowania. Również w moim przypadku pracuję w zespole, w którym oczekuje się, że wszyscy będą mieć takie same ustawienia Git (tzn. Rozróżnia wielkość liter), więc jeśli je wyłączę, musi to być tymczasowe.
Steve Chambers
44

Pod OSX, aby uniknąć tego problemu i uniknąć innych problemów z rozwijającymi się bez uwzględniania wielkości liter systemu plików, można użyć Narzędzia dyskowego, aby utworzyć przypadek wrażliwe wirtualny napęd / dysk obrazu.

Uruchom narzędzie dyskowe, utwórz nowy obraz dysku i użyj następujących ustawień (lub zmień, jak chcesz, ale rozróżniaj wielkość liter):

Zrzut ekranu narzędzia Mac Disk Utility

Pamiętaj, aby powiedzieć gitowi, że jest teraz na FS z rozróżnianiem wielkości liter:

git config core.ignorecase false
użytkownik1821510
źródło
15
Nie, jądro ma w systemie OSX w pełni rozróżniający wielkość liter dysk startowy. Będziesz musiał żyć bez źle napisanych aplikacji (ahem, Adobe) lub uruchamiać je we własnej głupiej maszynie wirtualnej, ale warto, jeśli kodujesz głównie dla systemów * nix.
Mike Marcacci,
1
To jedyna opcja, która działa poprawnie. Wypróbowałem resztę, a ty w ten czy inny sposób skończysz w marynacie. Rozwiąż problem poprawnie, wykonując to.
John Hunt
2
Zauważ, że Narzędzie dyskowe ma błąd OS X 10.11 - Nie tworzy obrazów z rozróżnianiem wielkości liter. Musisz użyć narzędzia wiersza polecenia hdiutil. apple.stackexchange.com/questions/217915/…
dellsala
7
Z APFS w High Sierra jest to jeszcze łatwiejsze. Kliknij ikonę dysku z plusem i dodaj wielkość liter bez rozróżniania wielkości. Po prostu dzieli przestrzeń z głównym woluminem i montuje w / Volumes / volume-name.
Michael Fox
21

Wypróbowałem następujące rozwiązania z innych odpowiedzi i one nie działały:

Jeśli Twoje repozytorium jest hostowane zdalnie (GitHub, GitLab, BitBucket), możesz zmienić nazwę pliku w miejscu pochodzenia (GitHub.com) i wymusić zmianę nazwy pliku w odgórny sposób.

Poniższe instrukcje dotyczą GitHub, jednak ich ogólna idea powinna dotyczyć każdej platformy zdalnego hostowania repozytoriów. Pamiętaj, że typ pliku, którego nazwę próbujesz zmienić, ma znaczenie, to znaczy, czy jest to typ pliku, który GitHub uważa za edytowalny (kod, tekst itp.) Lub nieedytowalny (obraz, plik binarny itp.) W przeglądarce.

  1. Odwiedź GitHub.com
  2. Przejdź do swojego repozytorium na GitHub.com i wybierz oddział, w którym pracujesz
  3. Za pomocą narzędzia do nawigacji po plikach witryny przejdź do pliku, którego nazwę chcesz zmienić
  4. Czy GitHub pozwala edytować plik w przeglądarce?
    • a.) Edytowalne
      1. Kliknij ikonę „Edytuj ten plik” (wygląda jak ołówek)
      2. Zmień nazwę pliku podczas wprowadzania tekstu
    • b.) Nieedytowalne
      1. Otwórz przycisk „Pobierz” w nowej karcie i zapisz plik na komputerze
      2. Zmień nazwę pobranego pliku
      3. Na poprzedniej karcie na GitHub.com kliknij ikonę „Usuń ten plik” (wygląda jak kosz)
      4. Upewnij się, że branchnamejest zaznaczony przycisk opcji „Zatwierdź bezpośrednio w oddziale”, a następnie kliknij przycisk „Zatwierdź zmiany”
      5. W tym samym katalogu na GitHub.com kliknij przycisk „Prześlij pliki”
      6. Prześlij plik o zmienionej nazwie z komputera
  5. Upewnij się, że branchnamejest zaznaczony przycisk opcji „Zatwierdź bezpośrednio w oddziale”, a następnie kliknij przycisk „Zatwierdź zmiany”
  6. Lokalnie kasa / pobieranie / wyciąganie gałęzi
  7. Gotowy
gmeben
źródło
Zmieniłem nazwę bezpośrednio na BitBucket i zadziałało. Dzięki.
rsc
Dobrze wiedzieć. Ta technika powinna teoretycznie działać na dowolnej platformie hostingowej repozytorium, ale chciałbym wiedzieć, czy istnieją takie, z którymi nie będzie działać.
gmeben
Nie działa w przypadku plików, których nie można edytować w przeglądarce, takich jak obrazy lub PDF; oczywiście nie ma opcji edycji.
Abhijit Sarkar
@AbhijitSarkar Dobra uwaga. Zaktualizowałem odpowiedź na te przypadki. Przetestowałem i zweryfikowałem, że te instrukcje działają.
gmeben
Czy ktoś zdoła zmienić nazwę katalogu w ten sposób?
Solvitieg
20

Podobnie do odpowiedzi @ Sijmen, to właśnie działało dla mnie w OSX podczas zmiany nazwy katalogu (zainspirowany odpowiedzią z innego postu):

git mv CSS CSS2
git mv CSS2 css

Samo działanie git mv CSS cssspowodowało błąd nieprawidłowego argumentu: fatal: renaming '/static/CSS' failed: Invalid argumentbyć może dlatego, że system plików OSX nie rozróżnia wielkości liter

ps BTW, jeśli używasz Django, collectstatic również nie rozpoznałby różnicy wielkości liter i musiałbyś to zrobić ręcznie, również w statycznym katalogu głównym

Anupam
źródło
18

1) zmień nazwę pliku Name.jpgnaname1.jpg

2) zatwierdzić usunięty plik Name.jpg

3) zmień nazwę pliku name1.jpgnaname.jpg

4) Popraw plik dodany name.jpgdo poprzedniego zatwierdzenia

git add
git commit --amend
razon
źródło
2
Otrzymuję to fatal: bad source, source=name1.jpg, destination=name.jpgw kroku 3. Czy masz jakieś sugestie? Thx
Anthony Kong
1
Po prostu nie możesz wykonać zatwierdzenia git add.
Alex78191
Wygląda bardzo pospiesznie, prawda? Lub łatanie małp.
jeromej
18

Zastosowałem następujące kroki:

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

Dla mnie to proste rozwiązanie

andrewvergel
źródło
To jest rozwiązanie. I w przeciwieństwie do innych odpowiedzi działa dobrze, gdy zmieniasz nazwy partii. Na glamourphilly.org musieliśmy zmieniać każdy plik .Jpg na .jpg. W Finderze możesz dokonywać takich zmian nazw partii, a ta odpowiedź pozwala ci to sprawdzić.
William Entriken
11

Możemy użyć polecenia git mv. Przykład poniżej, jeśli zmieniliśmy nazwę pliku abcDEF.js na abcdef.js, możemy uruchomić następującą komendę z terminala

git mv -f .\abcDEF.js  .\abcdef.js
Sandeep Shukla
źródło
8

Mac OSX High Sierra 10.13 nieco to rozwiązuje. Po prostu stwórz wirtualną partycję APFS dla swoich projektów git, domyślnie nie ma limitu rozmiaru i nie zajmuje miejsca.

  1. W Narzędziu dyskowym kliknij przycisk +, gdy wybrany jest dysk kontenera
  2. Wybierz APFS (rozróżnia wielkość liter) w formacie
  3. Nazwij to Sensitive
  4. Zysk
  5. Opcjonalnie: Utwórz folder w programie Sensitive o nazwie gitiln -s /Volumes/Sensitive/git /Users/johndoe/git

Twój dysk będzie włączony /Volumes/Sensitive/

wprowadź opis zdjęcia tutaj

Jak zatwierdzić zmiany nazw plików z rozróżnianiem wielkości liter w Git?

Ray Foss
źródło
Uwielbiam tę sugestię, która elegancko i bezboleśnie rozwiązuje problem bez uciekania się do brzydkich obejść. Dzięki!
Phil Gleghorn
4

Kilka razy spotkałem się z tym problemem na MacOS. Git rozróżnia małe i wielkie litery, ale Mac zachowuje tylko małe i wielkie litery.

Ktoś zatwierdza plik: Foobar.javai po kilku dniach decyduje się zmienić nazwę na FooBar.java. Gdy pobierzesz najnowszy kod, nie powiedzie sięThe following untracked working tree files would be overwritten by checkout...

Jedyny niezawodny sposób, w jaki to widziałem, to:

  1. git rm Foobar.java
  2. Zatwierdź to z komunikatem, którego nie możesz przegapić git commit -m 'TEMP COMMIT!!'
  3. Ciągnąć
  4. Spowoduje to pojawienie się konfliktu, zmuszając Cię do scalenia konfliktu - ponieważ Twoja zmiana go usunęła, ale inna zmiana zmieniła jej nazwę (stąd problem)
    1. Zaakceptuj zmianę, którą jest „usunięcie”
    2. git rebase --continue
  5. Teraz upuść obejścia git rebase -i HEAD~2idropTEMP COMMIT!!
  6. Potwierdź, że plik jest teraz wywoływany FooBar.java
Ashwin Jayaprakash
źródło
3

Kiedy dokonałeś wielu zmian nazw plików, a niektóre z nich to tylko zmiana wielkości obudowy, trudno jest zapamiętać, która jest która. ręcznie „git move” plik może być dość pracochłonny. Tak więc, co zrobiłbym podczas zadań zmiany nazwy pliku:

  1. usuń wszystkie pliki inne niż git i folder do innego folderu / repozytorium.
  2. zatwierdź bieżący pusty folder git (pokaże się, gdy wszystkie pliki zostaną usunięte).
  3. dodaj wszystkie pliki z powrotem do oryginalnego folderu / repozytorium git.
  4. zatwierdzić bieżący niepusty folder git.

To rozwiąże wszystkie problemy ze sprawami bez próby ustalenia, które pliki lub foldery zostały zmienione.

Ricardo Virtudazo Jr
źródło
Dlaczego nie git commmit --amendw ust. 4? W przeciwnym razie nastąpi dodatkowe zatwierdzenie po usunięciu wszystkich plików. Lub możesz użyć git rebase -ido squasha.
Alex78191
1

Jeśli nic nie działało, użyj git rm nazwa_pliku, aby usunąć plik z dysku i dodać go z powrotem.

gopal Pandey
źródło
0

Wziąłem @CBarr odpowiedź i napisał Pythona 3 Script to zrobić z listą plików:

#!/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()
użytkownik
źródło