Comment valider uniquement les changements de nom de fichier sensibles à la casse dans Git?

1303

J'ai changé un nom quelques fichiers par de-majuscule la première lettre, comme Name.jpgà name.jpg. Git ne reconnaît pas ces changements et j'ai dû supprimer les fichiers et les télécharger à nouveau. Existe-t-il un moyen pour Git d'être sensible à la casse lors de la vérification des changements dans les noms de fichiers? Je n'ai apporté aucune modification au fichier lui-même.

Gil Shulman
la source
4
@nif si ce n'est pas tout à fait correct, Git a en fait un paramètre de configuration qui contrôle si oui ou non il respecte la casse.
6
Voir stackoverflow.com/a/24979063/6309 : depuis git 2.0.1, un simple git mvfonctionne.
VonC
Référez ce post. J'ai pu valider mais en utilisant juste git commit -m "msg" sans aucun chemin de fichier comme paramètres. Il a mis à jour l'index et archivé le fichier. [Lien] stackoverflow.com/questions/35790113/…
ARKS

Réponses:

1518

Vous pouvez utiliser git mv :

git mv -f OldFileNameCase newfilenamecase
Keith Smiley
la source
12
cela me donne «le répertoire source est vide» alors qu'il ne l'est pas
WiseStrawberry
6
Utiliser MacOS ici (FS insensible à la casse) et -f ont fonctionné! Merci pour l'astuce
caesarsol
49
Dans les versions récentes, vous n'avez plus besoin du -fdrapeau.
Joshua Pinter
8
N'oubliez pas de donner le chemin complet du fichier. Évidemment, je sais, mais ça m'a pris un moment
rickrizzo
7
Au sommet voté commentaire: vous avez besoin du -fcommutateur avec la dernière git (2,18) sinon vous pourriez obtenir l' fatal: destination existserreur.
DeepSpace101
1040

Git a un paramètre de configuration qu'il indique si d'être sensible à la casse ou insensible: core.ignorecase. Pour dire à Git d'être sensible à la casse, définissez simplement ce paramètre sur false:

git config core.ignorecase false

Documentation

De la git configdocumentation :

core.ignorecase

Si true, cette option permet à diverses solutions de contournement pour permettre à git de mieux fonctionner sur les systèmes de fichiers qui ne sont pas sensibles à la casse, comme FAT. Par exemple, si une liste de répertoires trouve makefilequand git attend Makefile, git supposera qu'il s'agit vraiment du même fichier et continuera à s'en souvenir Makefile.

La valeur par défaut est false, sauf que git-clone (1) ou git-init (1) sonderont et définiront core.ignorecasetrue si approprié lorsque le référentiel est créé.

Systèmes de fichiers insensibles à la casse

Les deux systèmes d'exploitation les plus populaires qui ont des systèmes de fichiers insensibles à la casse que je connais sont

  • les fenêtres
  • OS X

la source
9
Soit dit en passant, je ne pense pas que Mac OS X lui-même ne soit pas sensible à la casse. C'est plutôt le système de fichiers qui détermine la sensibilité à la casse. Lors du formatage d'une partition HFS +, les utilisateurs peuvent choisir de la rendre sensible à la casse ou insensible. La casse est insensible à la casse.
spaaarky21
225
Il semble très intéressant de noter dans cette réponse que la définition de cette option falsesur un système de fichiers insensible à la casse est une mauvaise idée . Ce n'est pas forcément évident. Par exemple, je viens de l'essayer sur mon Mac, pensant que cela résoudrait mes problèmes, puis j'ai renommé un fichier de productPageCtrl.jsà ProductPageCtrl.js. git statusa vu un nouveau fichier appelé ProductPageCtrl.jsmais ne pensait pas qu'il productPageCtrl.jsavait été supprimé. Lorsque j'ai ajouté les nouveaux fichiers, validés et poussés vers GitHub, le référentiel GitHub contenait désormais les deux fichiers même si mon référentiel local (supposément à jour) n'en avait qu'un.
Mark Amery
5
@MarkAmery Cela ressemble beaucoup à un bug dans votre client Git. Avez-vous déposé un rapport?
Domi
24
@Domi ce n'est pas un bug, c'est un comportement attendu. C'est en fait une mauvaise idée de mettre ceci sur faux sur un système de fichiers insensible car c'est ce qui se passe. La raison pour laquelle git n'a pas vu le fichier en minuscules supprimé est que le système de fichiers ne le signale pas comme supprimé car il ignore le cas alors que git ne le fait pas avec cette option définie sur false. Ce n'est pas que les noms de fichiers n'ont pas de minuscules vs majuscules sur ntfs ou fat, c'est juste que la recherche de nom de fichier ignore le cas.
ohcibi
15
@Domi git est assez intelligent. C'est pourquoi vous ne devez pas définir ce paramètre sur false sur un système de fichiers insensible à la casse. Utilisez git mvpour déplacer le fichier et voir comment git le gère. Si vous déplacez le fichier sans git, il n'y a rien que git puisse faire car le système de fichiers ne dit pas la vérité à git. C'est un problème de ntfs / fat / hfs et thelike et non git / linux.
ohcibi
158

En utilisant SourceTree, j'ai pu tout faire à partir de l'interface utilisateur

  1. Renommer FILE.ext enwhatever.ext
  2. Étape ce fichier
  3. Maintenant renommer whatever.ext àfile.ext
  4. Mettre ce fichier en scène de nouveau

C'est un peu fastidieux, mais si vous n'avez besoin de le faire que pour quelques fichiers, c'est assez rapide

CBarr
la source
5
La même chose avec git bash
Alex78191
3
"Mettre en scène ce fichier" est la partie importante - aucune des autres réponses ci-dessus n'a fonctionné pour moi. Cela fonctionnait en fait avec l'ancienne invite de commande Windows.
Vlad Sabev
1
Je ne savais pas que cela fonctionnait dans la zone de rassemblement. Mais dans mon cas, je voulais modifier les noms de dossier ainsi que certains fichiers dans ces dossiers. J'ai donc d'abord renommé tous les dossiers en noms temporaires. Validé les nouveaux noms (tous les fichiers à l'intérieur) et les fichiers "supprimés". Git les a tous marqués comme "renommés". Puis renommé tous ces dossiers à leurs nouvelles versions de cas et validé à nouveau. Enfin, fusionné ces 2 commits. Mais d'après ce que vous avez écrit, j'aurais pu faire le tout directement via la zone de repérage, sans créer 2 commits + fusion.
ThermoX
3
Fonctionne également avec gitkraken sur le nom du dossier.
Philippe Matray
J'ai écrit un script Python 3 pour faire ce travail fastidieux: stackoverflow.com/a/58159822/4934640
utilisateur
126

C'est ce que j'ai fait sur OS X:

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

Deux étapes car sinon j'ai eu une erreur "fichier existe". Peut-être que cela peut être fait en une seule étape en ajoutant --cachedou tel.

Sijmen Mulder
la source
21
comme l'indique la réponse du haut, -f(force) est le drapeau que vous recherchez
rperryng
5
@rperryng - non, l' -findicateur n'aide pas si le FS sous-jacent n'est pas sensible à la casse. Cependant, la solution en deux étapes a fonctionné pour moi
HEKTO
Utilisation d'un FS insensible à la casse (sur Mac) et ça marche -f! Merci pour l'astuce
caesarsol
Cela a également fonctionné avec un dossier sur Windows sans le -fdrapeau.
nich
git -c "core.ignorecase=false" add .prendra en compte les fichiers dont la casse a été modifiée pour validation.
nietonfir
67

Il est parfois utile de modifier temporairement la sensibilité à la casse de Git:

Méthode n ° 1 - Modifier la sensibilité à la casse pour une seule commande:

git -c core.ignorecase=true checkout mybranchpour désactiver la sensibilité à la casse pour une seule checkoutcommande. Ou plus généralement: . (Nous remercions VonC d'avoir suggéré cela dans les commentaires.)git -c core.ignorecase= <<true or false>> <<command>>

Méthode n ° 2 - Modifier la sensibilité à la casse pour plusieurs commandes:

Pour modifier le paramètre plus longtemps (par exemple, si plusieurs commandes doivent être exécutées avant de le modifier à nouveau):

  1. git config core.ignorecase(cela renvoie le réglage actuel, par exemple false).
  2. git config core.ignorecase <<true or false>> - définissez le nouveau réglage souhaité.
  3. ... Exécutez plusieurs autres commandes ...
  4. git config core.ignorecase <<false or true>> - remettre la valeur de configuration à son paramètre précédent.
Steve Chambers
la source
1
Pourquoi pas directement git -c core.ignorecase=<true or false> checkout <<branch>>? Rien à réinitialiser après.
VonC
2
J'ai eu une expérience étrange du travail de core.ignorecase proposé lors du passage de minuscules en majuscules, mais pas pour les majuscules en minuscules. semble que la seule solution fiable consiste à cesser d'utiliser un système d'exploitation qui ne reconnaît pas la casse du nom de fichier.
aspiringGuru
Y a-t-il une raison pour que ce soit un changement temporaire? Est-ce que cela causerait un problème si je laissais juste les paramètres modifiés en respectant la casse?
cytsunny
Cela peut dépendre de quelques facteurs, en particulier si le système de fichiers cible est sensible à la casse - voir en.wikipedia.org/wiki/Case_sensitivity#In_filesystems . La modification temporaire peut être nécessaire si le système de fichiers de déploiement a une sensibilité à la casse différente du système de fichiers utilisé pour le développement. De plus, dans mon cas, je travaille dans une équipe où tout le monde devrait avoir les mêmes paramètres Git (c'est-à-dire sensibles à la casse), donc si je le désactive, cela doit être temporaire.
Steve Chambers
44

Sous OSX, pour éviter ce problème et éviter d'autres problèmes de développement sur un système de fichiers ne respectant pas la casse, vous pouvez utiliser l'Utilitaire de disque pour créer une image de disque / disque virtuel sensible à la casse .

Exécutez l'utilitaire de disque, créez une nouvelle image disque et utilisez les paramètres suivants (ou modifiez comme vous le souhaitez, mais gardez-le sensible à la casse):

Capture d'écran de l'utilitaire de disque Mac

Assurez-vous de dire à git qu'il est maintenant sur un FS sensible à la casse:

git config core.ignorecase false
user1821510
la source
15
Non, le nucléaire exécute un lecteur de démarrage entièrement sensible à la casse sur OSX. Vous devrez vivre sans applications mal écrites (ahem, Adobe), ou exécuter celles-ci dans leur propre machine virtuelle stupide, mais cela vaut la peine si vous codez principalement pour les systèmes * nix.
Mike Marcacci
1
C'est la seule option qui fonctionne correctement. J'ai essayé le reste et vous vous retrouvez dans un cornichon d'une manière ou d'une autre. Résolvez le problème correctement en procédant ainsi.
John Hunt
2
Notez que l'Utilitaire de disque a un bug OS X 10.11 - Il ne créera pas d'images sensibles à la casse. Vous devez utiliser l'outil de ligne de commande hdiutil. apple.stackexchange.com/questions/217915/…
dellsala
7
Avec APFS dans High Sierra, c'est encore plus facile. Cliquez sur l'icône d'un lecteur avec un plus et ajoutez un volume sensible à la casse sans limite de taille. Il partage simplement l'espace avec le volume principal et se monte dans / Volumes / nom-volume.
Michael Fox
21

J'ai essayé les solutions suivantes à partir des autres réponses et elles n'ont pas fonctionné:

Si votre référentiel est hébergé à distance (GitHub, GitLab, BitBucket), vous pouvez renommer le fichier à l'origine (GitHub.com) et forcer le renommage du fichier de manière descendante.

Les instructions ci-dessous concernent GitHub, mais l'idée générale derrière elles devrait s'appliquer à toute plate-forme d'hébergement de référentiel distant. Gardez à l'esprit le type de fichier que vous essayez de renommer, c'est-à-dire s'il s'agit d'un type de fichier que GitHub considère comme modifiable (code, texte, etc.) ou non modifiable (image, binaire, etc.) dans le navigateur.

  1. Visitez GitHub.com
  2. Accédez à votre référentiel sur GitHub.com et sélectionnez la branche dans laquelle vous travaillez
  3. À l'aide de l'outil de navigation dans les fichiers du site, accédez au fichier que vous souhaitez renommer
  4. GitHub vous permet-il de modifier le fichier dans le navigateur?
    • a.) Modifiable
      1. Cliquez sur l'icône "Modifier ce fichier" (il ressemble à un crayon)
      2. Modifier le nom de fichier dans la saisie de texte du nom de fichier
    • b.) Non modifiable
      1. Ouvrez le bouton "Télécharger" dans un nouvel onglet et enregistrez le fichier sur votre ordinateur
      2. Renommez le fichier téléchargé
      3. Dans l'onglet précédent sur GitHub.com, cliquez sur l'icône "Supprimer ce fichier" (cela ressemble à une poubelle)
      4. Assurez-vous que "S'engager directement branchname bouton radio succursale» est sélectionné et cliquez sur le bouton «Valider les modifications»
      5. Dans le même répertoire sur GitHub.com, cliquez sur le bouton "Télécharger les fichiers"
      6. Téléchargez le fichier renommé depuis votre ordinateur
  5. Assurez-vous que "S'engager directement branchname bouton radio succursale» est sélectionné et cliquez sur le bouton «Valider les modifications»
  6. Localement, checkout / fetch / pull the branch
  7. Terminé
gmeben
la source
J'ai renommé directement BitBucket et cela a fonctionné. Merci.
rsc
Bon à savoir. Cette technique devrait théoriquement fonctionner sur n'importe quelle plate-forme d'hébergement de référentiel, mais je serais intéressé de savoir s'il y en a avec laquelle elle ne fonctionnerait pas.
gmeben
Ne fonctionne pas pour les fichiers qui ne peuvent pas être modifiés dans le navigateur, comme les images ou les PDF; il n'y a évidemment pas d'option d'édition.
Abhijit Sarkar
@AbhijitSarkar Bon point. J'ai mis à jour ma réponse pour ces cas. J'ai testé et vérifié le fonctionnement de ces instructions.
gmeben
Quelqu'un parvient-il à renommer un répertoire de cette façon?
Solvitieg
21

Semblable à la réponse de @ Sijmen, c'est ce qui a fonctionné pour moi sur OSX lors du changement de nom d'un répertoire (inspiré par cette réponse d'un autre post):

git mv CSS CSS2
git mv CSS2 css

Faire simplement a git mv CSS cssdonné l'erreur d'argument invalide: fatal: renaming '/static/CSS' failed: Invalid argumentpeut-être parce que le système de fichiers d'OSX n'est pas sensible à la casse

ps BTW si vous utilisez Django, collectstatic ne reconnaîtra pas non plus la différence de casse et vous devrez également faire manuellement ce qui précède dans le répertoire racine statique

Anupam
la source
19

1) renommer le fichier Name.jpg enname1.jpg

2) Valider le fichier supprimé Name.jpg

3) renommer le fichier name1.jpg enname.jpg

4) Amender le fichier ajouté name.jpgau commit précédent

git add
git commit --amend
razon
la source
2
J'obtiens ceci fatal: bad source, source=name1.jpg, destination=name.jpgà l'étape 3. Avez-vous une suggestion? Thx
Anthony Kong
1
Vous ne pouvez pas faire de commit juste git add.
Alex78191
Ça a l'air très hacky, non? Ou patch de singe.
jeromej
18

J'ai utilisé ces étapes suivantes:

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

Pour moi, c'est une solution simple

andrewvergel
la source
Voilà la solution. Et contrairement aux autres réponses, cela fonctionne bien lorsque vous effectuez des renommages par lots. Sur glamourphilly.org, nous devions changer chaque .Jpg en .jpg. Dans le Finder, vous pouvez faire des renommages par lots comme ça et cette réponse vous permet de l'archiver.
William Entriken
11

Nous pouvons utiliser la commande git mv. Exemple ci-dessous, si nous avons renommé le fichier abcDEF.js en abcdef.js, nous pouvons exécuter la commande suivante à partir du terminal

git mv -f .\abcDEF.js  .\abcdef.js
Sandeep Shukla
la source
8

Mac OSX High Sierra 10.13 corrige quelque peu ce problème. Créez simplement une partition APFS virtuelle pour vos projets git, par défaut, elle n'a pas de limite de taille et ne prend pas d'espace.

  1. Dans l'Utilitaire de disque, cliquez sur le bouton + lorsque le disque conteneur est sélectionné
  2. Sélectionnez APFS (sensible à la casse) sous le format
  3. Nomme le Sensitive
  4. Profit
  5. Facultatif: créez un dossier dans Sensitive appelé gitetln -s /Volumes/Sensitive/git /Users/johndoe/git

Votre lecteur sera en /Volumes/Sensitive/

entrez la description de l'image ici

Comment valider uniquement les changements de nom de fichier sensibles à la casse dans Git?

Ray Foss
la source
J'adore cette suggestion, elle résout le problème avec élégance et sans douleur sans recourir à de vilaines solutions de contournement. Merci!
Phil Gleghorn
4

J'ai rencontré ce problème plusieurs fois sur MacOS. Git est sensible à la casse mais Mac ne fait que préserver la casse.

Quelqu'un valide un fichier: Foobar.javaet après quelques jours décide de le renommer enFooBar.java . Lorsque vous extrayez le dernier code, il échoue avecThe following untracked working tree files would be overwritten by checkout...

Le seul moyen fiable que j'ai vu pour résoudre ce problème est:

  1. git rm Foobar.java
  2. Engagez-le avec un message que vous ne pouvez pas manquer git commit -m 'TEMP COMMIT!!'
  3. Tirer
  4. Cela fera apparaître un conflit vous obligeant à fusionner le conflit - car votre modification l'a supprimé, mais l'autre modification l'a renommé (d'où le problème).
    1. Acceptez votre modification qui est la «suppression»
    2. git rebase --continue
  5. Maintenant , déposez votre solution de contournement git rebase -i HEAD~2et droplaTEMP COMMIT!!
  6. Confirmez que le fichier est maintenant appelé FooBar.java
Ashwin Jayaprakash
la source
3

Lorsque vous avez fait beaucoup de renommages de fichiers et que certains d'entre eux ne sont qu'un changement de boîtier, il est difficile de se rappeler lequel est lequel. manuellement «déplacer git» le fichier peut être un peu de travail. Donc ce que je ferais pendant mes tâches de changement de nom de fichier sont:

  1. supprimez tous les fichiers et dossiers non git dans un autre dossier / référentiel.
  2. valider le dossier git vide actuel (cela apparaîtra comme tous les fichiers supprimés.)
  3. ajoutez tous les fichiers dans le dossier / référentiel git d'origine.
  4. valider le dossier git non vide en cours.

Cela résoudra tous les problèmes de cas sans essayer de comprendre quels fichiers ou dossiers vous avez renommé.

Ricardo Virtudazo Jr
la source
Pourquoi pas git commmit --amendau paragraphe 4? Sinon, il y aura un commit supplémentaire avec la suppression de tous les fichiers. Ou vous pouvez utiliser git rebase -iavec de la courge.
Alex78191
1

Si rien ne fonctionne, utilisez git rm filename pour supprimer le fichier du disque et l'ajouter à nouveau.

gopal Pandey
la source
0

J'ai pris la réponse @CBarr et j'ai écrit un script Python 3 pour le faire avec une liste de fichiers:

#!/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()
utilisateur
la source