web-dev-qa-db-fra.com

Git exclut le fichier pour une branche

Je veux ignorer certains fichiers d'une branche sans avoir à compter sur un fichier .gitignore suivi qui sera écrasé lors de la fusion avec d'autres branches.

J'ai suivi de près une réponse Stack Overflow ainsi que l'article de blog lié , mais mon dépôt ne semble pas reconnaître la excludesfile spécifiée dans mon .git/config. La documentation Git ( git-config , gitignore ) ne semble pas montrer comment spécifier et s’adresser un fichier d’exclusion pour une branche spécifique.

Mon .git/config ressemble à ceci:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        ignorecase = true
        precomposeunicode = true
        excludesfile = +/info/exclude

[branch "myspecialbranch"]
        excludesfile = +/info/exclude_specialbranch

Mon fichier .git/info/exclude ressemble à ceci (par défaut, je ne le touchais pas):

# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store

Je n’ai pas de fichier .gitignore dans mon "specialbranch".

Si j'essaie d'ignorer un fichier tel que info.php, mon fichier .git/info/exclude_specialbranch ressemble à ceci:

info.php

… Mais il n’ignore pas le fichier.

Si j'exécute git status --ignored, il ne répertorie que le fichier .DS_Store à partir du fichier par défaut exclude.

Cependant, si j'ajoute info.php à mon fichier .git/info/exclude:

# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
info.php

il ignore parfaitement le fichier.

Notez que cela fonctionne toujours sans la ligne excludesfile = +/info/exclude sous [core] dans .git/config. Git semble savoir où se trouve la exclude à l'échelle du système sans que je doive le dire.

J'ai l'impression que .git/config ne reconnaît pas l'adresse de mon fichier personnalisé excluant le fichier:

excludesfile = +/info/exclude_specialbranch

… Probablement à cause de l'utilisation de + pour décrire l'emplacement du répertoire .git.

Quelle est la bonne méthode pour adresser les fichiers d’exclusion personnalisés dans les versions (les plus récentes) de Git?

J'utilise OSX 10.9.5 et Git version 2.2.1.

16
goredwards

Git ne supporte pas les fichiers exclus par branche

Vous essayez de réaliser quelque chose que Git ne supporte pas. Le blog post est la source originale de ce canular que la réponse Stack Overflow only parrote. Comme indiqué dans les commentaires sous cette réponse, même le billet de blog d'origine contient une discussion qui montre que la solution ne fonctionne pas et renvoie à un billet de blog plus récent qui indique que même l'auteur est incapable de reproduire le problème.

Pourquoi ça ne marche pas? Si vous lisez man gitignore et man git-config , vous trouverez juste core.excludesfile référencé. Pas de branch.<name>.excludesfile ici. Le core.excludesfile est conçu pour vous permettre d'exclure, par exemple, Les fichiers .swp ou autres éléments temporaires utilisés par votre logiciel.

core.excludesfile

En plus de .gitignore (par répertoire) et .git/info/exclude, Git recherche dans ce fichier des modèles de fichiers qui ne doivent pas être suivis. "~/" est étendu à la valeur de $HOME et "~user/" au répertoire de base de l'utilisateur spécifié. Sa valeur par défaut est $XDG_CONFIG_HOME/git/ignore. Si $XDG_CONFIG_HOME est non défini ou vide, c'est plutôt $HOME/.config/git/ignore qui est utilisé. Voir gitignore (5) .

Solution de contournement

Je crois que la meilleure approximation d'un fichier par branche exclut est obtenue en utilisant le crochet post-checkout et la réalisation du .gitignore via un lien symbolique.

Chaque branche aurait par exemple un répertoire .gitignores avec des fichiers nommés d'après les branches correspondantes. Ensuite, il y aurait un fichier .gitignores/__default qui serait utilisé par défaut. Le .gitignore serait exclu par tous les fichiers exclus et serait créé par le crochet post-paiement en tant que lien symbolique vers le fichier correspondant dans .gitignores.

Si vous ne voulez pas suivre les fichiers exclus, vous pouvez faire de même avec le fichier .git/info/exclude en tant que lien symbolique vers .git/info/excludes/__default etc.

24
Palec

Voici un script que j'ai écrit pour faire ceci:

#!/bin/bash                                                                      

# This is designed to allow per-branch un-ignoring of certain files.
# Use case: Compiled CSS files on master to Push to server.
# A special .gitignore file will be present on master at
# {$gitignorePath}/{$disabledMasterGitignoreName} and that file should 
# enable the css files using the ! flag. @https://git-scm.com/docs/gitignore

# When the branch specified by script parameters
# is checked out, {$gitignorePath}/{$disabledMasterGitignoreName} is 
# copied to .gitignore. 
# On other branches this gitignore file is named $disabledMasterGitignoreName, versioned,
# and {$gitignorePath}.gitignore will be deleted. Note, you must ignore 
# {$gitignorePath}.gitignore from your main .gitignore file
#
# To enable put this file in your path and call this script
# in .git/hooks/post-checkout with pass a list of single-space-separated branches that
# will enable the branch-specific .gitignore.

# One caveat is that you can only merge into the branch containing the .gitignore
# file. Otherwise you'll end up re-committing the files. This is fine if you are
# using gitflow and `master` contains your special .gitigore using the ! syntax
# that is un-ignoring files.
#
# Background: @http://stackoverflow.com/questions/29579546/git-excludesfile-for-a-branch

set -e                                                                           

gitignorePath='docroot/sites/all/themes'
disabledMasterGitignoreName='.gitignore_master--disabled'
#branchWithGitignoreEnabled='master'

branch=$(git rev-parse --abbrev-ref HEAD)

gitignoreRoot="$(git rev-parse --show-toplevel)/${gitignorePath}"

if [ -f "${gitignorePath}/.gitignore" ]
then
    masterGitignoreExists=true
fi

if [ -f "${gitignorePath}/${disabledMasterGitignoreName}" ]
then
    disabledMasterGitignoreExists=true
fi

IFS=' ' read -a params <<< "$@"

if [[ " ${params[@]} " =~ " ${branch} " ]]
then
  if [ $disabledMasterGitignoreExists ]
  then
    cp -f "${gitignoreRoot}/${disabledMasterGitignoreName}" "${gitignoreRoot}/.gitignore"
    echo "Enabled ${gitignorePath}/.gitignore"
  fi
Elif [ $masterGitignoreExists ]
then
    rm -f "${gitignorePath}/.gitignore"
    if [ masterGitignoreExists ]
    then
      echo "Disabled ${gitignorePath}/.gitignore"
    fi
fi
1
Jeremy John