En utilisant git, comment ignorer un fichier dans une branche mais le faire valider dans une autre branche?

157

J'ai un projet que je déploie sur Heroku . L'arborescence du code source comprend un tas de fichiers mp3 (le site Web sera pour un projet d'enregistrement dans lequel j'ai été fortement impliqué).

Je voudrais mettre le code source pour cela sur GitHub , mais GitHub a une limite de 300 Mo sur leurs comptes gratuits. Je ne veux pas utiliser 50 Mo de ma limite sur un tas de fichiers mp3. Évidemment, je pourrais les ajouter au .gitignorefichier pour les garder hors de mon dépôt.

Cependant, je déploie sur Heroku en utilisant git push heroku. Les fichiers mp3 doivent être présents dans la branche que je pousse vers Heroku pour qu'ils soient déployés.

Idéalement, j'aimerais .gitignoreles fichiers mp3 dans ma branche principale locale afin que lorsque je les envoie sur GitHub, les mp3 ne soient pas inclus. Ensuite, je garderais une branche de production locale qui a les mp3 commis plutôt que ignorés. Pour déployer, je fusionnais le maître dans la production, puis je poussais la branche de production vers Heroku.

Je ne peux pas faire fonctionner ça correctement.

Voici un exemple de ce que j'essaie de faire ...

$ git init git-ignore-test
$ cd git-ignore-test
$ echo "*.ignored" >> .gitignore
$ git add .gitignore && git commit -m "Ignore .ignored files"
$ touch Foo.ignored

À ce stade, Foo.ignored est ignoré dans ma branche master, mais il est toujours présent, donc mon projet peut l'utiliser.

$ git checkout -b unignored
$ cat /dev/null > .gitignore
$ git add Foo.ignored .gitignore && git commit -m "Unignore .ignored files"

Maintenant, j'ai une branche avec ces fichiers validés, comme je le souhaite. Cependant, lorsque je reviens à ma branche principale, Foo.ignored est parti.

Quelqu'un a-t-il des suggestions pour une meilleure façon de configurer cela?

Edit: juste pour clarifier, je veux que les fichiers mp3 soient présents dans les deux branches afin que lorsque je lance le site localement (en utilisant l'une ou l'autre branche) le site fonctionne. Je veux juste que les fichiers soient ignorés dans une branche, donc quand je pousse vers GitHub, ils ne le sont pas non plus. Habituellement .gitignore fonctionne bien pour ce genre de chose (c'est-à-dire garder une copie locale d'un fichier qui n'est pas inclus dans un push vers une télécommande), mais quand je passe à la branche avec les fichiers archivés, puis retourne au branche avec les fichiers ignorés, les fichiers disparaissent.

Myron Marston
la source
Pourquoi les fichiers MP3 doivent-ils être enregistrés dans le référentiel?
Dan Loewenherz
4
Avec heroku, s'engager dans votre dépôt est le seul moyen d'obtenir des fichiers inclus avec votre application lorsque vous déployez. La seule alternative est d'utiliser quelque chose comme Amazon S3 pour servir les mp3, mais je préférerais éviter cela.
Myron Marston
On dirait que vous trébuchez sur des dollars pour économiser quelques centimes ... Le Rackspace Cloud est très simple à installer, et il en coûterait très peu de stocker <1 Go de fichiers là-bas ...
gahooa
3
Je remarque que vous avez marqué une réponse comme correcte, mais d'après ce que j'ai lu, elle n'est peut-être pas correcte. Avez-vous déjà essayé la réponse et cela a-t-il fonctionné pour vous?
boucle le
2
Hors sujet: Avez-vous envisagé d'utiliser un autre hôte de référentiel open source? BitBucket n'a pas de limite de taille sur leurs référentiels Git, qu'ils soient dans un compte gratuit ou non (ils mentionnent cependant de garder la taille dans des limites raisonnables). Tant que votre dépôt ne devient pas incontrôlable, cela peut être une option. REMARQUE: je ne suis pas associé à BitBucket, juste un client satisfait.
NightOwl888

Réponses:

84

Cette solution semble fonctionner uniquement pour certaines versions corrigées de git. Voir une nouvelle réponse indiquant des solutions de contournement et une autre réponse et les commentaires suivants pour un indice sur les versions qui peuvent fonctionner.

J'ai écrit un article de blog sur la façon d'utiliser efficacement le excludesfilepour différentes branches, comme un pour le github public et un pour le déploiement d'heroku.

Voici le rapide et sale:

$ git branch public_viewing
$ cd .git/
$ touch info/exclude_from_public_viewing
$ echo "path/to/secret/file" > info/exclude_from_public_viewing 

puis dans le fichier .git / config ajoutez ces lignes:

[core]
excludesfile = +info/exclude


[branch "public_viewing"]
excludesfile = +info/exclude_from_public_viewing

Maintenant, tous les éléments ignorés globaux sont dans le info/excludefichier et la branche spécifique est dans leinfo/exclude_from_public_viewing

J'espère que cela pourra aider!

http://cogniton-mind.tumblr.com/post/1423976659/howto-gitignore-for-different-branches

Cognition.Mind
la source
1
Désolé d'avoir pris si longtemps ... mais si vous ne supprimez pas les fichiers .gitignore, ils seront par défaut ceux-là en premier.
Cognition.Mind
4
Cela ne fonctionne pas pour moi, même lorsque le projet n'utilise pas .gitignore. Cela vous dérange-t-il de fournir une transcription des commandes configurant cela à partir de zéro ( git init, ...), et la version de Git que vous avez utilisée?
Davor Cubranic
34
Cette solution ne fonctionne pas. Il y a eu des discussions sur le blog, et personne là-bas n'a pu faire fonctionner cela non plus.
spuder
2
Dans Git vanilla, je suis presque sûr que cela ne fonctionne pas et ne l'a jamais fait. Ceux d'entre vous qui ont réussi à reproduire cela, pouvez-vous partager votre version de Git et d'autres informations pertinentes sur votre environnement? Peut-être avez-vous une version corrigée des responsables de paquets Git de votre distribution.
Palec le
20

Conseil important : La réponse acceptée par Cognition.Mind ne fonctionne plus (depuis plusieurs années maintenant, ou peut-être pour les versions vanilla de git); voir les commentaires. Une réponse valide et une solution de contournement peuvent être trouvées ici:

https://stackoverflow.com/a/29583813/2157640

Une autre solution de contournement alternative (fonctionnant pour mon problème particulier, mais exigeant des opérations de stockage manuel ou la mise en œuvre d'un hook) serait git stash -u -a. Ceci est fastidieux lorsque les différences sont importantes.

Et enfin, la solution avec laquelle je vais maintenant est d'avoir forké ma VM dans laquelle nous maintenons notre environnement de développement et configuré de info/excludesmanière appropriée pour la branche, en supprimant respectivement les fichiers / dossiers incriminés et non validés.

Murphy
la source
14

Je conseillerais fortement d'envisager de mettre ces fichiers MP3 sur S3. Les faire faire partie de votre poussée Heroku (et donc de votre slug Heroku) ralentira considérablement le temps de démarrage de votre dyno. Puisque Heroku utilise EC2, si les fichiers sont sur S3 et ne sont accessibles que par votre application (si les utilisateurs ne sont pas directement liés à S3), vous ne paierez même pas de frais de bande passante, seulement les frais de stockage de 50 Mo.

David Dollar
la source
13

Disons que nous voulons ignorer le builddossier de toutes les autres branches sauf la productionbranche. Comme nous voulons pousser le builddossier en production.

1) buildN'incluez pas dans .gitignore. Si vous faites cela, il sera toujours ignoré pour toutes les branches.

2) Créez un fichier exclude_from_public_viewingdans le dossier ./.git/info(Ce dossier existe déjà)touch ./.git/info/exclude_from_public_viewing

3) À l'intérieur, exclude_from_public_viewingécrivez une ligne (comme vous essayez d'ignorer buildtoutes les branches). !build

4) Il existe un fichier existant .git/info/exclude. Nous devons y ajouter la ligne suivante.

 build

Nous voulons ignorer le builddossier mais ne l'avons pas ajouté dans .gitignore. Alors, comment git saura quoi ignorer? La réponse est que nous l'ajoutons au excludefichier et que nous transmettons conditionnellement ce fichier àgit config

5) Maintenant, nous devons annuler conditionnellement le builddossier pour la productionbranche. pour faire cela, procédez comme suit

6) Il existe un fichier existant appelé que ./.git/confignous devons ajouter suivant -

une) excludesfile = +info/exclude ci-dessous[core]

[core]
     excludesfile = +info/exclude

b) Créez une nouvelle section à la fin de ./.git/config as

[branch "production"]
    excludesfile = +info/exclude_from_public_viewing

Solution 2

Il existe une solution alternative intelligente. Disons que vous voulez ajouterbuild/ dossier dans la productionbranche et l'ignorer dans toutes les autres branches.

1) Ajoutez-le à votre gitignorefichier.

2) Dans la branche de production, tout en faisant git add, forcez l'ajout de builddossier:git add -f --all build/

sapy
la source
Et cela diffère de la solution acceptée comment? Avec quelle version de git l'avez-vous testé? Comme l'indique la réponse liée, cela échoue car il n'y a plus de support pour branch.<name>.excludesfiledans git (plus?), Seulement pour core.excludesfile, et mes propres tests semblaient l'affirmer.
Murphy
@murphy cela fonctionne bien avec git version 2.7.4 (Apple Git-66)et je ne l'ai pas utilisé branch.<name>.excludesfile dans ma solution.
sapy le
4
@sapy: j'ai essayé cela selon le cas d'utilisation d'OP, et le fichier disparaît toujours lorsque je passe de la production au master. Notez que le dossier "build" doit être validé dans la branche "production". (De plus, je note que si je ne valide pas le dossier "build" dans la branche "production", la branche "production" ignore la présence du dossier "build" - c'est-à-dire que la [branche "production"] excludesfile config ne ne fonctionne pas). J'utilise exactement la même version de git que la vôtre. J'ai aussi essayé l'approche [branche "production"] pour ignorer le fichier uniquement dans la branche production, cela ne fonctionne pas non plus, comme l'a dit Murphy.
justhalf
La solution 2 était quelque chose que je recherchais. Merci!
Vyacheslav Cotruta
4

Avez-vous essayé de faire en sorte que .gitignore soit différent dans votre branche?

Vous devriez pouvoir ignorer ce que vous voulez en fonction de la branche dans laquelle vous vous trouvez tant que les fichiers ne sont pas suivis sur cette branche.

KEND
la source
6
J'ai essayé ça. Si vous regardez les commandes que j'ai postées ci-dessus, vous verrez que c'est exactement ce que j'ai fait. Le problème est que lorsque je passe de la branche avec les fichiers archivés à la branche avec les fichiers ignorés, git rejette les fichiers. Je veux garder les mp3 dans ma branche principale pour que le site fonctionne correctement en mode dev, même si les fichiers sont ignorés.
Myron Marston
1
il a déjà dit que c'est ce qu'il a fait. peut-être que supprimer simplement cette réponse serait peut-être mieux :-) cela cause une distraction.
blamb
3

1. Résumé

  1. J'utilise Travis CI pour le déploiement ( il prend en charge le déploiement Heroku )
  2. J'ajoute à mon .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore

    misc- n'importe quel dossier, en contient un autre .gitignore.

    mvFichier de déplacement de commande UNIX ; écraser, si le fichier existe déjà.

Lorsque Travis CI déploie un projet, Travis CI ne poussera pas au déploiement de fichiers et de dossiers de fournisseur , qui ignorent dans misc/.gitignore(pas dans l'original .gitignoredes sources).


2. Limitations

  1. Cette réponse peut ne pas convenir à toutes les conditions de l'auteur. Mais cette réponse répond à la question "En utilisant git, comment ignorer un fichier dans une branche mais le faire valider dans une autre branche?"
  2. Je ne suis pas un utilisateur Heroku, mes exemples pour GitHub , pas pour Heroku. Les données de cette réponse fonctionnent pour moi dans GitHub, mais peuvent ne pas fonctionner sur Heroku.

3. Pertinence

Cette réponse est pertinente pour avril 2018. À l'avenir, les données de cette réponse pourraient être obsolètes.


4. Démonstration

mon vrai projet .

Exemple de déploiement réussi .

4.1. Tâche

Je déploie mon projet de la branche src vers la branche dest du même référentiel.

Je veux, ce fichier PaletteMira.suricate-profile:

  • Machine locale - existe pour toutes les succursales,
  • branche distante src - n'existe pas,
  • dist branche distante - existe.

Si j'ai bien compris l'auteur de la question, il a une tâche similaire.

4.2. src

branche sources - SashaYAML .

Partie de .travis.yml:

before_deploy:
- mv misc/.gitignore .gitignore

deploy:
  provider: pages
  on:
    branch: SashaYAML
  keep-history: true
  skip-cleanup: true
  target-branch: SashaDevelop
  repo: Kristinita/PaletteMira
  github-token: $GITHUB_TOKEN
  committer-from-gh: true
  project-name: PaletteMira
verbose: true

Partie de .gitignore:

*.sublime-snippet
*.suricate-profile

Partie de misc/.gitignore

*.sublime-snippet

*.suricate-profilepas dedans misc/.gitignore.

PaletteMira.suricate-profile n'existe pas dans cette branche à distance, mais existe localement.

4.3. dest

succursale de destination - SashaDevelop

Partie de .gitignore:

*.sublime-snippet

*.suricate-profilepas dedans misc/.gitignore.

PaletteMira.suricate-profileexiste pour cette branche à distance et localement.

4.4. Étapes à suivre pour reproduire

J'active le référentiel PaletteMira GitHub pour Travis CI → Je règle la variable d'environnement $GITHUB_TOKEN avec la valeur - mon jeton GitHub → Je fais un commit dans ma branche src.

Si aucune erreur, je dois obtenir le comportement attendu .

Саша Черных
la source
0

Pouvez-vous vous engager et pousser depuis Heroku?

par exemple, ajoutez l'audio, poussez-les vers github et dans heroku, supprimez les fichiers de la copie de travail sur Heroku. Supprimez l'audio du référentiel mais pas du disque, puis repoussez cette modification vers github.

À M
la source
0

Github prend désormais en charge le stockage de fichiers volumineux, voir plus ici https://git-lfs.github.com/

John Lozano
la source