242 votes

Faire git supprimer automatiquement de fuite des espaces blancs avant de s'engager

Je suis à l'aide de git avec mon équipe et à supprimer les changements d'espaces de mes diffs, les journaux, la fusion, etc. Je suppose que la meilleure façon de le faire serait de git pour supprimer automatiquement de fuite d'espaces (et d'autres espaces d'erreurs) de tous les commits qu'ils sont appliqués.

J'ai essayé d'ajouter les éléments suivants à par ~/.gitconfig le fichier mais il ne fait rien quand je m'engage. Peut-être qu'il est conçu pour quelque chose de différent. Quelle est la solution?

[core]
    whitespace = trailing-space,space-before-tab
[apply]
    whitespace = fix

Je suis l'aide de ruby dans le cas où quelqu'un a des rubis d'idées précises. Automatique de formatage de code avant de commettre serait la prochaine étape, mais c'est un problème difficile et pas vraiment la cause d'un gros problème.

124voto

VonC Points 414372

Ces paramètres (core.whitespace et apply.whitespace) ne sont pas là pour enlever fuite des espaces, mais à:

  • core.whitespace: les détecter et de déclencher des erreurs
  • apply.whitespace: et pour les dépouiller, mais seulement au cours de patch, pas "automatiquement"

Je crois que le git hook pre-commit permettrait de faire un meilleur travail pour que (inclut la suppression de fuite d'espace).


Notez qu'à tout moment, vous pouvez choisir de ne pas exécuter les pre-commit hook:

  • temporairement: git commit --no-verify .
  • permanence: cd .git/hooks/ ; chmod -x pre-commit

Attention: par défaut, un pré-script de validation (comme ce l'un), n'a pas un "supprimer de fuite" fonctionnalité", mais un "avertissement" caractéristique, comme:

if (/\s$/) {
    bad_line("trailing whitespace", $_);
}

Vous pouvez, toutefois, construire un meilleur pre-commit hook, surtout quand on considère que:

S'engageant dans git, avec seulement quelques changements par rapport à la zone de transit toujours conduit à une "atomique" de révision qui peut n'avoir jamais existé comme une copie de travail et ne peuvent pas travailler.


Par exemple, oldman propose dans une autre réponse d'un pre-commit hook qui permet de détecter et de supprimer l'espace.
Depuis que le crochet d'obtenir le nom de fichier de chaque dossier, je vous recommande d'être prudent pour certains types de fichiers: vous ne voulez pas supprimer de fuite espaces en .md (markdown) des fichiers!

49voto

ntc2 Points 1643

Vous pouvez tromper Git dans la fixation de l'espace pour vous, en incitant Git dans le traitement de vos modifications en tant que patch. Contrairement à la "pre-commit hook" des solutions, ces solutions d'ajouter des espaces de fixation des commandes Git.

Oui, ce sont des hacks.


Des solutions robustes

La suite de Git alias sont prises à partir de mon ~/.gitconfig.

Par "solide", je veux dire que ces alias exécuter sans erreur, en faisant la bonne chose, peu importe si l'arbre ou de l'index sont sales.

Si vous souhaitez exécuter directement dans le shell, sans la création d'un Git alias, il suffit de copier et coller tout ce qui est entre les guillemets (en supposant que votre shell est Bash comme).

Fixer l'index, mais pas l'arbre

La suite de fixws Git alias résout tous les espaces des erreurs dans l'index, le cas échéant, mais ne pas toucher à l'arbre:

# Logic:
#
# The 'git stash save' fails if the tree is clean (instead of
# creating an empty stash :P). So, we only 'stash' and 'pop' if
# the tree is dirty.
#
# The 'git rebase --whitespace=fix HEAD~' throws away the commit
# if it's empty, and adding '--keep-empty' prevents the whitespace
# from being fixed. So, we first check that the index is dirty.
#
# Also:
# - '(! git diff-index --quiet --cached HEAD)' is true (zero) if
#   the index is dirty
# - '(! git diff-files --quiet .)' is true if the tree is dirty
#
# The 'rebase --whitespace=fix' trick is from here:
# http://stackoverflow.com/a/19156679/470844
fixws = !"\
  if (! git diff-files --quiet .) && \
     (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git stash save FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~ && \
    git reset --soft HEAD~ && \
    git stash pop ; \
  elif (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git rebase --whitespace=fix HEAD~ && \
    git reset --soft HEAD~ ; \
  fi"

L'idée est de lancer git fixws avant git commit si vous avez les espaces des erreurs dans l'index.

Corrigé de l'indice et de l'arbre

La suite de fixws-global-tree-and-index Git alias résout tous les espaces des erreurs dans l'index et l'arbre, le cas échéant:

# The different cases are:
# - dirty tree and dirty index
# - dirty tree and clean index
# - clean tree and dirty index
#
# We have to consider separate cases because the 'git rebase
# --whitespace=fix' is not compatible with empty commits (adding
# '--keep-empty' makes Git not fix the whitespace :P).
fixws-global-tree-and-index = !"\
  if (! git diff-files --quiet .) && \
     (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git add -u :/ && \
    git commit -m FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~2 && \
    git reset HEAD~ && \
    git reset --soft HEAD~ ; \
  elif (! git diff-files --quiet .) ; then \
    git add -u :/ && \
    git commit -m FIXWS_SAVE_TREE && \
    git rebase --whitespace=fix HEAD~ && \
    git reset HEAD~ ; \
  elif (! git diff-index --quiet --cached HEAD) ; then \
    git commit -m FIXWS_SAVE_INDEX && \
    git rebase --whitespace=fix HEAD~ && \
    git reset --soft HEAD~ ; \
  fi"

Pour fixer les espaces dans des fichiers non versionnés, ne

git add --intent-to-add <unversioned files> && git fixws-global-tree-and-index

Simple, mais pas des solutions robustes

Ces versions sont plus faciles à copier et coller, mais ils ne font pas le bonne chose si de leur côté les conditions ne sont pas remplies.

Fixer le sous-arbre enraciné dans le répertoire courant (mais réinitialise l'index s'il n'est pas vide)

À l'aide de git add -e "modifier" les patchs à l'identité de l'éditeur de ::

(export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue .) && git checkout . && git reset

Fixer et préserver l'index (mais échoue si l'arbre est sale ou si l'indice est vide)

git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset --soft HEAD~

Fixer l'arbre et de l'index (mais réinitialise l'index s'il n'est pas vide)

git add -u :/ && git commit -m TEMP && git rebase --whitespace=fix HEAD~ && git reset HEAD~

Explication de l' export GIT_EDITOR=: && git -c apply.whitespace=fix add -ue . astuce

Avant que j'ai appris à propos de l' git rebase --whitespace=fix truc de cette réponse , j'ai été en utilisant le plus compliqué git add astuce partout.

Si nous avons fait manuellement:

  1. Ensemble apply.whitespace de fix (vous n'avez qu'à le faire une seule fois):

    git config apply.whitespace fix
    

    Cela indique à Git pour fixer les espaces dans les patchs.

  2. Convaincre Git pour traiter vos modifications en tant que patch:

    git add -up .
    

    Frapper un+enterpour sélectionner tous les changements pour chaque fichier. Vous obtiendrez un avertissement sur Git la fixation de votre espace erreurs.
    (git -c color.ui=auto diff à ce point révèle que votre non-indexé changements sont exactement les espaces d'erreurs).

  3. Supprimer les espaces les erreurs de votre copie de travail:

    git checkout .
    
  4. Apportez vos modifications (si vous n'êtes pas prêt à s'engager eux):

    git reset
    

L' GIT_EDITOR=: des moyens de les utiliser : comme l'éditeur, et comme une commande : est l'identité.

30voto

Casey Points 19286

J'ai trouvé un git pre-commit hook qui supprime fin d'espaces.

  #!/bin/sh

  if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
     against=HEAD
  else
     # Initial commit: diff against an empty tree object
     against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
  fi
  # Find files with trailing whitespace
  for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq` ; do
     # Fix them!
     sed -i 's/[[:space:]]*$//' "$FILE"
     git add "$FILE"
  done
  exit

20voto

AlexChaffee Points 2979

Sur Mac OS (ou, probablement, tout BSD), le sed paramètres de commande doivent être légèrement différentes. Essayez ceci:

#!/bin/sh

if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
   against=HEAD
else
   # Initial commit: diff against an empty tree object
   against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -E 's/:[0-9]+:.*//' | uniq` ; do
    # Fix them!
    sed -i '' -E 's/[[:space:]]*$//' "$FILE"
    git add "$FILE"
done

Enregistrez ce fichier en tant que .git/hooks/pre-commit -- ou regarder pour celui qui est déjà là, et coller la partie inférieure morceau quelque part à l'intérieur. Et n'oubliez pas d' chmod a+x de trop.

Ou pour une utilisation mondiale (via Git commit crochets - paramètres globaux), vous pouvez le mettre dans $GIT_PREFIX/git-core/templates/hooks (où GIT_PREFIX est /usr ou /usr/local /usr/share ou /opt/local/share) et exécutez git init à l'intérieur de votre repos.

Selon git help init:

L'exécution de la commande git init dans un référentiel existant est sûr. Il ne remplace pas les choses qui sont déjà là. La principale raison de la reprise de git init est de ramasser les modèles récemment ajoutés.

10voto

urandom Points 175

J'ai écrit cette pre-commit hook, qui supprime uniquement la fuite d'espace blanc à partir de lignes que vous avez changé/ajouté, depuis les suggestions précédentes ont tendance à créer des illisible s'engage si les fichiers cibles ont trop de fuite des blancs.

#!/bin/sh

if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
   against=HEAD
else
   # Initial commit: diff against an empty tree object
   against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

IFS='
'

files=$(git diff-index --check --cached $against -- | sed '/^[+-]/d' | perl -pe 's/:[0-9]+:.*//' | uniq)
for file in $files ; do
    diff=$(git diff --cached $file)
    if test "$(git config diff.noprefix)" = "true"; then
        prefix=0
    else
        prefix=1
    fi
    echo "$diff" | patch -R -p$prefix
    diff=$(echo "$diff" | perl -pe 's/[ \t]+$// if m{^\+}')
    out=$(echo "$diff" | patch -p$prefix -f -s -t -o -)
    if [ $? -eq 0 ]; then
        echo "$diff" | patch -p$prefix -f -t -s
    fi
    git add $file
done

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X