Usando git, ¿cómo ignoro un archivo en una rama pero lo confirmo en otra rama?

157

Tengo un proyecto que estoy implementando en Heroku . El árbol de código fuente incluye un montón de archivos mp3 (el sitio web será para un proyecto de grabación en el que estuve muy involucrado).

Me gustaría poner el código fuente en GitHub , pero GitHub tiene un límite de 300 MB en sus cuentas gratuitas. No quiero usar 50 MB de mi límite en un montón de archivos mp3. Obviamente, podría agregarlos al .gitignorearchivo para mantenerlos fuera de mi repositorio.

Sin embargo, lo uso en Heroku usando git push heroku. Los archivos mp3 deben estar presentes en la rama que envío a Heroku para que se implementen.

Idealmente, me gustaría tener .gitignorelos archivos mp3 en mi rama maestra local para que cuando lo transfiera a GitHub, los mp3 no estén incluidos. Luego mantendría una rama de producción local que tiene los mp3 comprometidos en lugar de ignorados. Para implementar, fusionaría master en producción y luego empujaría la rama de producción a Heroku.

No puedo hacer que esto funcione bien.

Aquí hay un ejemplo de lo que estoy tratando de hacer ...

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

En este punto, Foo.ignored es ignorado en mi rama maestra, pero todavía está presente, por lo que mi proyecto puede usarlo.

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

Ahora tengo una rama con estos archivos comprometidos, como quiero. Sin embargo, cuando vuelvo a mi rama maestra, Foo.ignored se ha ido.

¿Alguien tiene alguna sugerencia para una mejor manera de configurar esto?

Editar: solo para aclarar, quiero que los archivos mp3 estén presentes en ambas ramas para que cuando ejecute el sitio localmente (usando cualquiera de las ramas) el sitio funcione. Solo quiero que los archivos se ignoren en una rama, por lo que cuando presiono a GitHub no se presionan también. Por lo general, .gitignore funciona bien para este tipo de cosas (es decir, mantener una copia local de un archivo que no se incluye en una inserción a un control remoto), pero cuando cambio a la rama con los archivos registrados y luego vuelvo a rama con los archivos ignorados, los archivos desaparecen.

Myron Marston
fuente
¿Por qué los archivos MP3 siempre tienen que estar comprometidos con el repositorio?
Dan Loewenherz
44
Con heroku, comprometerse con su repositorio es la única forma de obtener archivos incluidos con su aplicación cuando se implementa. La única alternativa es usar algo como Amazon S3 para servir los mp3, pero preferiría evitarlo.
Myron Marston el
Suena como que está tropezando con dólares para salvar centavos ... La nube de Rackspace es muy sencillo de obtener una configuración en adelante, y que costaría muy poco a la tienda <1 GB de archivos allí ...
gahooa
3
Noté que marcó una respuesta como correcta, pero por lo que leí puede no ser correcta. ¿Alguna vez probaste la respuesta y funcionó para ti?
bucle el
2
Fuera del tema: ¿Ha considerado usar otro host de repositorio de código abierto? BitBucket no tiene límite de tamaño en sus repositorios de Git, independientemente de si están en una cuenta gratuita o no (aunque mencionan mantener el tamaño dentro de lo razonable). Mientras su repositorio no esté fuera de control, esta podría ser una opción. NOTA: No estoy asociado con BitBucket, solo soy un cliente satisfecho.
NightOwl888

Respuestas:

84

Esta solución parece funcionar solo para ciertas versiones parcheadas de git. Vea una nueva respuesta que apunta a soluciones alternativas y otra respuesta y comentarios posteriores para obtener una pista sobre qué versiones pueden funcionar.

Escribí una publicación de blog sobre cómo usar efectivamente las excludesfilediferentes ramas, como una para github público y otra para la implementación de heroku.

Aquí está lo rápido y sucio:

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

luego en el archivo .git / config agregue estas líneas:

[core]
excludesfile = +info/exclude


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

Ahora todo el material de ignorar global está en el info/excludearchivo y la rama específica está en elinfo/exclude_from_public_viewing

¡Espero que ayude!

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

Cognition.Mind
fuente
1
Perdón por tomar tanto tiempo ... pero si no elimina los archivos .gitignore, los predeterminados serán los primeros.
Cognition.Mind
44
Esto no funciona para mí, incluso cuando el proyecto no utiliza .gitignore. ¿Le importaría proporcionar una transcripción de los comandos que configuran esto desde cero ( git init, ...) y la versión de Git que utilizó?
Davor Cubranic
34
Esta solución no funciona. Hubo una discusión en el blog, y nadie allí pudo hacer que esto funcione tampoco.
Spuder
2
En Vanilla Git, estoy bastante seguro de que esto no funciona y nunca lo hizo. Aquellos de ustedes que lograron reproducir esto, ¿pueden compartir su versión de Git y otra información relevante sobre su entorno? Tal vez tenga una versión parcheada de los mantenedores de paquetes Git de su distribución.
Palec
20

Sugerencia importante : la respuesta aceptada por Cognition.Mind ya no funciona (desde hace varios años, o tal vez para versiones de vainilla de git); ver los comentarios Puede encontrar una respuesta válida y una solución alternativa aquí:

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

Sería otra solución alternativa (trabajar para mi problema particular, pero exigir operaciones manuales de almacenamiento o la implementación de un gancho) git stash -u -a. Esto es tedioso cuando las diferencias son grandes.

Y finalmente, la solución con la que ahora estoy yendo es bifurcar mi VM en la que tenemos nuestro entorno de desarrollo y configurarla de manera info/excludesapropiada para la rama, eliminando respectivamente los archivos / carpetas ofensivos y no comprometidos.

Murphy
fuente
14

Recomiendo encarecidamente considerar poner esos archivos MP3 en S3. Hacer que sean parte de su empuje Heroku (y, por lo tanto, parte de su babosa Heroku) disminuirá en gran medida el tiempo de inicio de su dinamómetro. Dado que Heroku usa EC2, si los archivos están en S3 y solo su aplicación accede a ellos (si los usuarios no están directamente vinculados a S3), ni siquiera pagará ningún cargo por ancho de banda, solo el cargo por almacenar 50 MB.

David Dollar
fuente
13

Digamos que queremos ignorar la buildcarpeta de todas las demás ramas, excepto la productionrama. Como queremos empujar la buildcarpeta en producción.

1) No incluir builden .gitignore. Si lo hace, siempre se ignorará para todas las ramas.

2) Crear un archivo exclude_from_public_viewingdentro de la ./.git/infocarpeta (Esta carpeta ya existe)touch ./.git/info/exclude_from_public_viewing

3) En el interior, exclude_from_public_viewingescriba una línea (como está tratando de ignorar buildtodas las ramas). !build

4) Hay un archivo existente .git/info/exclude. Necesitamos agregar la siguiente línea en él.

 build

Queremos ignorar la buildcarpeta pero no la hemos agregado en .gitignore. Entonces, ¿cómo git sabrá qué ignorar? La respuesta es que lo estamos agregando al excludearchivo y condicionalmente pasando ese archivo agit config

5) Ahora tenemos que ignorar condicionalmente la buildcarpeta de la productionrama. para hacer eso realizar siguiente

6) Hay un archivo existente llamado ./.git/configque necesitamos agregar a continuación:

a) a excludesfile = +info/excludecontinuación[core]

[core]
     excludesfile = +info/exclude

b) Crear una nueva sección al final de ./.git/configas

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

Solución 2

Hay una solución alternativa inteligente. Digamos que desea agregar una build/carpeta en la productionrama e ignorarla en todas las demás ramas.

1) Agréguelo a su gitignorearchivo.

2) En la rama de producción, mientras lo hace git add, forzar agregar buildcarpeta:git add -f --all build/

sapy
fuente
Y esto difiere de la solución aceptada ¿cómo? ¿Con qué versión de git lo probaste? Como dice la respuesta vinculada, falla porque no hay soporte para branch.<name>.excludesfilegit (¿ya?), Solo para core.excludesfile, y mis propias pruebas parecían afirmar esto.
Murphy
@murphy funciona bien git version 2.7.4 (Apple Git-66)y no lo he usado branch.<name>.excludesfile en mi solución.
sapy
44
@sapy: Intenté esto de acuerdo con el caso de uso de OP, y el archivo aún desaparece cuando cambio de producción a maestro. Tenga en cuenta que la carpeta "build" debe confirmarse en la rama "producción". (Además, observo que si no confirmo la carpeta "build" en la rama "producción", la rama "producción" ignora la presencia de la carpeta "build", es decir, la [rama "producción"] excluye el archivo de configuración no no funciona). Yo uso exactamente la misma versión de git que la tuya. También probé el enfoque [rama "producción"] para ignorar el archivo solo en la rama de producción, tampoco funciona, como dijo Murphy.
justhalf
La solución 2 era algo que estaba buscando. ¡Gracias!
Vyacheslav Cotruta
4

¿Has intentado que .gitignore sea diferente en tu rama?

Debería poder ignorar lo que desea en función de la rama en la que se encuentre, siempre que no se rastreen los archivos en esa rama.

kEND
fuente
66
Lo he intentado Si observa los comandos que publiqué anteriormente, verá que eso es exactamente lo que hice. El problema es que cuando cambio de la rama con los archivos registrados a la rama con los archivos ignorados, git descarta los archivos. Quiero mantener los mp3 en mi rama maestra para que el sitio funcione correctamente en modo de desarrollo, aunque se ignoren los archivos.
Myron Marston el
1
él ya dijo que eso fue lo que hizo. tal vez solo eliminar esta respuesta podría ser mejor :-) está causando distracción.
blamb
3

1. Resumen

  1. Utilizo Travis CI para la implementación ( admite la implementación de Heroku )
  2. Agrego a mi .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore

    Donde misc: cualquier carpeta contiene otra .gitignore.

    mvComando UNIX mover archivo; sobrescribir, si el archivo ya existe.

Cuando el proyecto de implementación de Travis CI, Travis CI no presionará para implementar archivos y carpetas de proveedores , que se ignoran misc/.gitignore(no en el original .gitignorede las fuentes).


2. Limitaciones

  1. Esta respuesta puede no ser adecuada para todas las condiciones del autor. Pero esta respuesta responde a la pregunta "Utilizando git, ¿cómo ignoro un archivo en una rama pero lo confirmo en otra rama?"
  2. No soy usuario de Heroku, mis ejemplos para GitHub , no para Heroku. Los datos de esta respuesta me funcionan en GitHub, pero puede que no funcione en Heroku.

3. Relevancia

Esta respuesta es relevante para abril de 2018. En el futuro, los datos de esta respuesta pueden quedar obsoletos.


4. Demostración

Mi verdadero proyecto .

Ejemplo de implementación exitosa .

4.1. Tarea

Implemento mi proyecto desde la rama src a la rama dest del mismo repositorio.

Quiero ese archivo PaletteMira.suricate-profile:

  • Máquina local: existe para todas las sucursales,
  • rama remota src: no existe,
  • rama remota dest: existe.

Si entendí correctamente al autor de la pregunta, él tiene una tarea similar.

4.2. src

sucursal de fuentes - SashaYAML .

Parte 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

Parte de .gitignore:

*.sublime-snippet
*.suricate-profile

Parte de misc/.gitignore

*.sublime-snippet

*.suricate-profileno en misc/.gitignore.

PaletteMira.suricate-profile no existe en esta rama de forma remota, sino que existe localmente.

4.3. dest

sucursal de destino - SashaDevelop

Parte de .gitignore:

*.sublime-snippet

*.suricate-profileno en misc/.gitignore.

PaletteMira.suricate-profileexiste para esta sucursal de forma remota y local.

4.4. pasos para reproducir

Habilito el repositorio PaletteMira GitHub para Travis CI Establezco la variable de entorno $GITHUB_TOKEN con valor: mi token GitHub Realizo cualquier confirmación en mi rama src.

Si no hay errores, debo obtener el comportamiento esperado .

Саша Черных
fuente
0

¿Puedes cometer y empujar desde Heroku?

Por ejemplo, agregue el audio, póngalos en github y en heroku, elimine los archivos de la copia de trabajo en Heroku. Elimine el audio del repositorio pero no del disco, luego empuje ese cambio nuevamente a github.

Tom
fuente