Git peut-il basculer automatiquement entre les espaces et les tabulations?

196

J'utilise des onglets pour l'indentation dans mes programmes python, mais je voudrais collaborer (en utilisant git) avec des personnes qui utilisent des espaces à la place.

Existe-t-il un moyen pour git de convertir automatiquement entre les espaces et les tabulations (par exemple, 4 espaces = 1 tabulation) lors de la poussée / récupération? (similaire à la conversion CR / LF)

Olivier Verdier
la source
33
PEP8 est précisément mon problème. Tout le monde le suit et je suis coincé avec mes onglets. Il se trouve que je pense qu'une indentation = un onglet est la bonne chose à faire (pourquoi des espaces? Pourquoi 4 espaces? PEP8 n'explique pas cela ...). Quoi qu'il en soit, avec cette astuce git, je peux utiliser des onglets sur mon ordinateur et partager mon code avec tous les abonnés PEP8.
Olivier Verdier
7
Oh! J'utilise TextMate et je peux convertir des espaces en tabulations. Le truc c'est que quand j'appuie sur tab, j'aime que mon éditeur écrive ... tab. Donc, si je récupère un projet python avec des espaces, j'insérerai toutes sortes d'onglets. Je dois convertir manuellement en onglets, mais lorsque je m'enregistre, cela ressemble à 1000 suppressions, 1000 ajouts et mes collaborateurs ne seront pas satisfaits. :-)
Olivier Verdier
6
La raison pour laquelle PEP8 spécifie des espaces au lieu des tabulations est due aux règles d'indentation de continuation. Il existe deux façons de continuer une ligne trop longue dans une parenthèse. Si vous commencez une nouvelle ligne immédiatement après une parenthèse, vous en indiquez simplement une. Si vous placez à la place une partie du contenu de la parenthèse sur la première ligne, vous devez continuer la parenthèse sur la ligne suivante au niveau du retrait de la parenthèse d'ouverture. Si vous utilisez des onglets qui ne fonctionnent pas.
John Christopher Jones
2
@JohnChristopherJones pour cette situation, on pourrait utiliser des tabulations pour faire correspondre l'indentation avec la ligne précédente puis des espaces pour faire correspondre une position dans la ligne précédente. Cela peut être facilement converti en espaces. Malheureusement, l'inverse n'est pas vrai, car il mélange les informations d'indentation avec les informations d'alignement.
Patrick Parker

Réponses:

195

Voici la solution complète:

Dans votre référentiel, ajoutez un fichier .git/info/attributesqui contient:

*.py  filter=tabspace

Linux / Unix

Exécutez maintenant les commandes:

git config --global filter.tabspace.smudge 'unexpand --tabs=4 --first-only'
git config --global filter.tabspace.clean 'expand --tabs=4 --initial'

OS X

Installez d'abord les coreutils avec l'infusion:

brew install coreutils

Exécutez maintenant les commandes:

git config --global filter.tabspace.smudge 'gunexpand --tabs=4 --first-only'
git config --global filter.tabspace.clean 'gexpand --tabs=4 --initial'

Tous les systèmes

Vous pouvez maintenant consulter tous les fichiers de votre projet. Vous pouvez le faire avec:

git checkout HEAD -- **

et tous les fichiers python auront désormais des onglets au lieu d'espaces.

Modifier : modification de la commande de retrait forcé. Bien sûr, vous devez d'abord engager votre travail.

Olivier Verdier
la source
1
Le filtre propre ne fonctionne pas pour moi. Quand j'en ajoute. J'obtiens une erreur disant "erreur: filtre externe expand --tabs = 4 --initial failed". Je suis sous Windows. Cela fait-il une différence?
Jeremy Hicks
2
@Jeremy: expand / unxpand sont des commandes Unix. Vous devrez soit trouver des ports / équivalents Windows, soit utiliser quelque chose comme Cygwin
Tim
1
J'ai trouvé la version de travail de bast sourceforge.net/projects/gnuwin32/files/coreutils/5.3.0
hazzik
3
@ Marc-André Bon point. J'utilise en fait les versions coreutils. (Installez homebrew, puis exécutez brew install coreutils).
Olivier Verdier
2
Il semble que cela ne fonctionne plus, les filtres ne font rien pour moi. Après le paiement, les fichiers ont encore des espaces. Une mise à jour pour ceci?
Philipp Ludwig
141

Oui, une solution potentielle consiste à utiliser un pilote de filtre d'attribut git (voir aussi le livre GitPro ), pour définir un mécanisme de maculage / nettoyage.

texte alternatif

De cette façon:

  • chaque fois que vous extrayez des fichiers de votre référentiel, les espaces peuvent être convertis en onglets,
  • mais lorsque vous vous enregistrez (et envoyez et publiez), ces mêmes fichiers sont stockés en utilisant uniquement des espaces.

Vous pouvez déclarer ce pilote de filtre (nommé ici ' tabspace') dans le .git/info/attributes(pour un filtre appliqué à tous les fichiers du dépôt Git), avec le contenu suivant:

*.py  filter=tabspace

Exécutez maintenant les commandes:

# local config for the current repo
git config filter.tabspace.smudge 'script_to_make_tabs'
git config filter.tabspace.clean 'script_to_make_spaces'

Voir la réponse d' Olivier pour un exemple concret de travail d'un tel ensemble d'instructions pour nettoyer / nettoyer.

VonC
la source
Malheureusement, cela ne fonctionne tout simplement pas. J'ai suivi toutes les instructions, mais git n'applique pas le filtre. :-( Quand je passe à la caisse, le filtre de maculage n'est pas appliqué, et quand je m'enregistre, rien ne se passe non plus ... git est tellement frustrant parfois ...
Olivier Verdier
@Olivier: Étrange, je n'ai jamais eu de problème avec cela, tant que je limite soigneusement la portée du filtre d'attribut (à une sous-arborescence spécifique, pour un type spécifique de fichiers uniquement) afin de ne pas ralentir le checkout / check- en cours. Voir par exemple stackoverflow.com/questions/62264/…
VonC
Merci! Maintenant ça marche. Voir la solution complète: stackoverflow.com/questions/2316677/…
Olivier Verdier
@Vonc: on devrait peut-être retirer le --globaldrapeau, car cela impliquerait d'envoyer des espaces à chaque projet de collaboration ...
Willem Van Onsem
@CommuSoft uniquement aux projets qui ont le droit .gitattributes. Mais oui, il est plus facile de comprendre si la configuration est conservée localement au dépôt. J'ai édité la réponse.
VonC
39

Informations très utiles pour tous ceux qui utilisent GitHub (ou un autre service similaire)

~/.gitconfig

[filter "tabspace"]
    smudge = unexpand --tabs=4 --first-only
    clean = expand --tabs=4 --initial
[filter "tabspace2"]
    smudge = unexpand --tabs=2 --first-only
    clean = expand --tabs=2 --initial

Ensuite, j'ai deux fichiers: attributes

*.js  filter=tabspace
*.html  filter=tabspace
*.css  filter=tabspace
*.json  filter=tabspace

et attributes2

*.js  filter=tabspace2
*.html  filter=tabspace2
*.css  filter=tabspace2
*.json  filter=tabspace2

Travailler sur des projets personnels

mkdir project
cd project
git init
cp ~/path/to/attributes .git/info/

De cette façon, lorsque vous poussez enfin votre travail sur github, cela ne semblera pas idiot dans la vue de code avec 8 space tabslaquelle est le comportement par défaut dans tous les navigateurs.

Contribuer à d'autres projets

mkdir project
cd project
git init
cp ~/path/to/attributes2 .git/info/attributes
git remote add origin [email protected]:some/repo.git
git pull origin branch

De cette façon, vous pouvez travailler avec des onglets normaux sur des 2 space indentedprojets.

Bien sûr, vous pouvez écrire une solution similaire pour la conversion, 4 space to 2 spacece qui est le cas si vous souhaitez contribuer à des projets publiés par moi et que vous avez tendance à utiliser 2 espaces lors du développement.

simo
la source
2
Connexes: Stockage de git config dans le cadre du référentiel ; notez également que vous pouvez utiliser (et valider) un .gitattributesfichier dans votre référentiel
Tobias Kienzler
1

Si vous êtes sur Windows, vous avez quelques étapes supplémentaires pour que la solution de @Olivier Verdier fonctionne.

  1. Télécharger CoreUtils pour Windows
  2. Après l'installation, placez l'emplacement d'installation dans votre PATH ( Comment ajouter une variable de chemin )
  3. J'ai renommé expand.exe en gexpand.exe car il existe déjà un utilitaire de développement Windows.
odyth
la source