2010-03-27 4 views
31

Nous avons le dépôt git bare dans unix qui a des fichiers avec le même nom qui ne diffère que dans les cas.Git-Windows les noms de fichiers sensibles à la casse ne sont pas gérés correctement

Exemple:

GRANT.sql 
grant.sql 

Lorsque nous cloner le dépôt nu à partir unix dans une boîte de fenêtres, git status détecte le fichier modifié. L'arbre de travail est chargé uniquement avec grant.sql, mais l'état git compare grant.sql et GRANT.sql et affiche le fichier modifié dans l'arbre de travail.

J'ai essayé d'utiliser le fichier core.ignorecase false mais le résultat est le même.

Est-il possible de résoudre ce problème?

+0

Question géniale et la réponse de Greg vient de se poser! – Hazok

+0

Cela peut également se produire lorsque vous créez le fichier avec un boîtier différent dans différentes branches de Windows. – Thomas

Répondre

4

Je ne suis pas sûr que ce soit même possible. L'ignorecase de Git gère les anomalies dans le cas d'un fichier. Il ne fonctionnera pas autour de l'incapacité de Windows à avoir deux noms de fichiers dans le répertoire qui ne diffèrent que par cas.

FWIW, avoir deux noms de fichiers identiques mais pour leur cas est une très mauvaise idée, même sous Unix.

+0

Si seulement les développeurs du noyau Linux étaient d'accord avec vous ... –

36

Windows est insensible à la casse (plus précisément, cas-préservation). Il n'y a simplement aucun moyen possible d'exister deux fichiers dont les noms ne diffèrent que dans le cas: deux noms de fichiers qui ne diffèrent que dans le cas sont le même nom de fichier. Période. Par conséquent, Git parcourt le référentiel, vérifiant un fichier après l'autre, jusqu'à ce qu'il touche le premier des deux fichiers de problèmes. Git le vérifie, puis va plus loin dans ses affaires jusqu'à ce qu'il atteigne le second fichier. Encore une fois, Git le vérifie. Du point de vue de Windows, le nom de fichier est le même que le premier, le premier fichier est simplement écrasé par le second. Ce qui fait maintenant penser à Git que le premier fichier a été changé pour avoir le même contenu que le second. Notez que cela n'a rien à voir avec Git: il en serait exactement de même si vous aviez une archive tar, un fichier zip ou un dépôt Subversion.

Si vous voulez faire du développement sur plusieurs plates-formes différentes, vous devez respecter les restrictions de ces plates-formes et vous devez vous limiter au plus petit dénominateur commun de toutes les plates-formes que vous prenez en charge. Windows prend en charge ADS, Linux non. OSX prend en charge les forks de ressources, Windows non. BSD prend en charge la casse, Windows ne le fait pas. Donc, vous ne pouvez en utiliser aucun. C'est comme ça.

core.ignorecase ne va pas vous aider ici, car cela gère exactement le problème opposé.

+2

+1 pour une explication détaillée – cctan

+1

Cela ne veut pas dire que ça marche. Cela signifie que vous convertissez le comportement fou en une erreur manifeste. – jrodman

+1

Il existe certainement un moyen d'exister deux fichiers dont les noms diffèrent seulement dans le cas, mais il a besoin d'un changement de registre. Cygwin le fait, mais je ne sais pas si msys peut (il y a un drapeau spécial qui doit être passé dans l'API Win32): https://cygwin.com/cygwin-ug-net/using-specialnames.html – Matt

32

Je viens de rencontrer un problème similaire. Dans mon cas, les deux fichiers avec des noms similaires différant seulement dans le cas étaient dans un sous-répertoire qui n'était pas pertinent sur le clone Windows. Git 1.7 a une fonctionnalité sparse checkout qui vous permet d'exclure certains fichiers d'une copie de travail. Pour exclure ce répertoire:

git config core.sparsecheckout true 
echo '*' >.git/info/sparse-checkout 
echo '!unwanted_dir/' >>.git/info/sparse-checkout 
git read-tree --reset -u HEAD 

Après cela, le sous-répertoire unwanted_dir/ a été complètement disparu de ma copie de travail et Git continue de travailler avec le reste des fichiers comme d'habitude.

Si vos GRANT.sql et grant.sql ne sont pas pertinents sur le clone Windows, vous pouvez ajouter leurs noms à .git/info/sparse-checkout pour exclure ces fichiers spécifiquement.

+1

La réponse était juste géniale et fonctionne aussi pour les problèmes de nom de fichier. Merci d'avoir soulagé les maux de tête que j'ai eu !!! A donné un +1 il y a quelques mois. – Hazok

+1

Excellente solution! J'avais besoin que le paramètre soit 'core.sparseCheckout' pour le faire fonctionner –

+1

Le conseil est vraiment utile! Impressionnant! – Fei

1

Cygwin gère la sensibilité à la casse et les caractères amusants dans les noms de fichiers beaucoup mieux que MSys.

Modifier cette clé de Registre pour activer la sensibilité de cas dans Windows:

HKLM \ System \ CurrentControlSet \ Control \ Session Manager \ Kernel \ ObCaseInsensitive = 0

Voir here pour certaines mises en garde dans la façon dont la casse est prise en charge à Cygwin.

2

Si vous souhaitez conserver votre référentiel compatible avec les systèmes de fichiers non sensibles à la casse, vous pouvez ajouter un hook de validation qui vous empêche d'archiver les fichiers conflictuels.

#!/bin/bash 

# Save current state 
git stash -u -q --keep-index || exit 1 

# Get the list of clashing files in the whole repository 
CLASHING=`find "$(git rev-parse --show-toplevel)" | sort | uniq -d -i` 

# Restore previous state 
git stash pop -q 

if [[ $CLASHING ]]; then 
    echo "Found clashing files on case-insensitive file systems" 
    echo "$CLASHING" 
    exit 1 
fi 

exit 0 

Ce script nécessite la version git> = 1.7.7, car il utilise -u stash, afin d'éviter à défaut sur les fichiers non suivis.

+1

Il peut échouer sur les fichiers non suivis dans '.gitignore'. – djjeck

+0

Est-ce que quelqu'un sait comment obtenir l'arbre actuel, y compris les changements par étapes? Attention, il ne suffit pas d'ajouter 'git diff --staged' à' HEAD'; par exemple, cela ne fonctionnerait pas lorsque vous changez le cas sur un nom de fichier. – djjeck

+0

Excellente solution. Dire "Ne fais pas ça" est très inutile. Je n'imagine pas qu'un magasin raisonnable autoriserait deux fichiers ou dossiers qui ne diffèrent que dans le cas où ils utiliseraient Linux. –

1

La façon la plus simple de fixer effectivement la question est de renommer un des fichiers afin qu'ils ne seront pas en conflit sur un système de fichiers sensible à la casse comme Windows ou OS X.

Après une validation de la Linux/Système Unix où vous pouvez le plus facilement résoudre le problème tout ira bien sur Windows après une traction. Pour éviter ce problème, vous devez ajouter un crochet de validation similaire à celui suggéré par djjeck.

Les symptômes sous Windows pour ce genre sont très confus et comprennent:

  • fichiers qui montrent toujours aussi changé même si vous les rétablissez qui permet de changer les branches ou rebasage très difficile.
  • Deux copies du fichier avec les noms qui ne diffèrent que dans le cas où les deux montrent des changements dans git IUG

Puisque les deux fichiers ne peuvent pas coexister sur une affaire plate-forme insensible vous devez changer l'un des noms de fichiers pour éviter la difficulté.

Questions connexes