2012-01-04 13 views
32

Estoy implementando una aplicación Rails en Heroku (por ahora) a través de git, y también me gustaría tener una versión pública para que la gente la mire. Algunos archivos son confidenciales y solo deben enviarse y enviarse a la rama "heroku", pero no a la rama "pública". ¿Cuál es la mejor manera de hacerlo?Git: Ignorar archivos para el repositorio público, pero no para el privado

(I hago saber acerca de las variables de configuración de Heroku, que es grande como una solución temporal, pero no es divertido, siempre y cuando tenga que cambiar de alojamiento.)

Las dos ramas no deben ser sincronizado en todo momento: estoy de acuerdo con fusionar periódicamente la rama "maestra" en la rama "pública" y empujarla a github por separado.

he intentado varias cosas:

  • separados .gitignore archivos y un "nuestro" se funden estrategia - esto no funcionaba al principio, y después de jugar con él por un tiempo decidí que estaba haciendo demasiado complicado, así que pude conseguir una tarea aparentemente simple

  • utilizando un archivo personalizado exclude, y añadiendo lo siguiente a .git/config ... esto simplemente no funcionó:

.git/config

[branch "public"] 
    excludesfile = +info/exclude_from_public 

¿Cuál es la mejor manera de tener una cuota de depósito privado y público en el mismo código, pero ignorar los archivos confidenciales en el repositorio público?

Puede suponer que no se ha confirmado o enviado ningún código, es decir, este es un repositorio recién inicializado.

(Esta pregunta se ha hecho antes en varias formas, pero ninguna de las respuestas eran recta hacia adelante o las respuestas parecía realmente hacky. Sólo estoy aquí para pedir esto de una manera muy simple, y es de esperar recibir una respuesta muy simple.)

+0

¿Puedes eliminar los archivos en la rama pública? – Bill

+0

Sí, pero obtendré conflictos de combinación con '.gitignore' de esta manera, y los archivos se agregarán nuevamente a la rama' public' cuando ejecuto 'git merge master' – bricker

+0

Si confía en usar sistemas de control de versiones múltiples, podría usar darcs/mercurial/svn/bzr/whatever para la rama privada, y selectivamente presionar a git. – tripleee

Respuesta

17

Voy a poner en segundo lugar la respuesta del submódulo, pero trato de aclarar algo. En primer lugar, git no se ocupa de los archivos, sino de los commits. No hay forma de filtrar archivos o rutas en una rama porque una rama es realmente un puntero a una confirmación. Cuando excluye o ignora, simplemente evita que los archivos se agreguen a su repositorio. ninguno de los archivos de "archivos confidenciales" está incluso en el repositorio, solo en su directorio de trabajo.

El submódulo es solo una referencia a otro repositorio almacenado en su repositorio, y una confirmación específica que ese repositorio revisado está rastreando. se puede decir de actualización mediante

git submodule update --recursive sensitive-files 

Con el fin de simplificar las cosas, se puede cometer enlaces simbólicos en el lugar adecuado señalando el camino submódulo.

ln -sf sensitive-files/shadow passwd 

Luego se agrega el enlace simbólico como lo haría con cualquier otro archivo ..

Recuerde el submódulo es sólo un repositorio git desprotegido, puede restringir fácilmente el acceso a este registro real y crea el principal público.

Actualizado:

triste falté la notificación, si todavía está trabajando en esto.

Puede tener varios enlaces simbólicos en su repositorio privado haciendo referencia al repositorio privado (submódulo) que está desprotegido en un subdirectorio. Cada una de las bases de datos o la instancia utilizada por Rails podría ser un enlace simbólico a ese subdirectorio privado.

Además, no necesita un control remoto que apunte al repositorio privado, solo una entrada en el archivo .gitmodules que se mantiene automáticamente en git submodule. Aún necesitaría proteger el repositorio privado para que solo su instancia de Heroku pueda acceder a él. Para eso, le sugiero que instale la gitosis en un servidor si puede o puede usar alguna otra solución privada de hospedaje de git. Agregue la clave pública ssh que coincida con la clave privada de su instancia a la lista de usuarios permitidos. (No estoy familiarizado con cómo hacer esto en Heroku.)

Cuando insertas tus cambios en heroku, debes descargar recursivamente todos los submódulos mencionados en el repositorio.

+1

Gracias por aclarar. Probablemente acepte su respuesta; sin embargo, me gustaría aclarar un poco más. Necesitaré un repositorio privado de git para poder hacer esto, ¿correcto? Además, la información confidencial se encuentra en varios lugares de la estructura de directorios de mi Rails ... ¿Podría revisar el "repositorio privado" en las ubicaciones correctas, o el repositorio privado tendría que tener básicamente un tipo de archivo de base de datos que los archivos Rails podría hacer referencia? Por último, ¿mi repo en Heroku tendría una referencia remota del "repositorio privado", o podría verificarlo todo en Heroku como uno solo? ¡Gracias! – bricker

2

Una forma de hacer esto sería poner sus archivos privados en un submódulo, y hacer referencia a ese módulo desde su archivo público. (Alternativamente, puede poner sus archivos públicos en un submódulo, y consultar ese repositorio desde su repositorio privado.)

+0

Veo cómo podría funcionar esto, pero parece una forma demasiado compleja de simplemente ignorar dos archivos. Esperaré para ver lo que otros tienen que decir. Gracias por su respuesta. – bricker

+1

Esta estrategia no funciona si los archivos en cuestión están en el mismo directorio que los archivos normales en los que desea guardar un archivo. Los submódulos están destinados a reducir el gasto de otros proyectos, bibliotecas, etc., no para tratar un pequeño subconjunto de archivos dentro de un repositorio. –

1

Crear 2 ramas. La única rama que tiene los archivos privados no se enviará al repositorio público. Después de una combinación, restaure los archivos en cuestión con git checkout HEAD^ -- files that should not have been merged, rm other files, git add -A y git commit --amend -C HEAD. No estoy seguro de cuál es la diferencia en los archivos en cuestión, pero entiendes la idea. Haga un pequeño script para esto y estará listo para comenzar. Incluso podría enviar una lista de archivos confidenciales que haya confirmado en la raíz y la secuencia de comandos podría actuar fuera de eso.

+0

No entiendo muy bien este método ... ¿podría explicarlo un poco más? ¿Esto mantendrá los archivos confidenciales completamente fuera del historial de compromiso para el repositorio público? – bricker

+1

simplemente no presione la rama privada –

7

Puede crear un pre-commit hook en su repositorio local, aquí puede escribir una secuencia de comandos para verificar la rama actualmente desprotegida y eliminar los archivos ofensivos si están presentes antes de que se procese la confirmación. Esto evita que los archivos se graben en el historial de Git de la sucursal incorrecta.

#!/bin/bash 
current_branch="$(git branch | sed -e 's/^*//')" 
if [ $current_branch != "heroku" ]; then 
    // Delete sensitive files before commit 
    rm -f dir1/dir2/exclude_from_public 
    rm -f dir1/dir2/exclude_from_public_also 
fi 
exit 0 

Alternativamente, el guión podría simplemente comprobar si los archivos y devolver el código de salida "1", advirtiendo de que la cometen no puede proceder, ya que contiene los archivos confidenciales.

La advertencia es que tendrá que entregar este script a cualquier persona que esté trabajando en la sucursal heroku "privilegiada", y siempre tenerlo incluido en su repositorio local.

Lo ideal sería tener este cheque hecho en el lado del servidor también; pero, desafortunadamente, GitHub solo ofrece una variante Web del gancho posterior a la recepción, por lo tanto, a menos que sea su propio hosting repo, este enfoque solo puede realizarse localmente.

2

Aquí están algunas otras preguntas StackOverflow y respuestas a lo largo de la línea de "¿cómo se hace una fusión sin tener en cuenta algunos archivos":

El más simple que puedo pensar, es el uso de un alias 'ed fusión que eliminará los archivos privados antes de hacer la fusión cometió. Esto funcionaría si estás dispuesto a vivir con fusiones no rápidas. Aquí está el alias:

git config alias.merge-master-exclude-private '!git merge --no-commit --no-ff master && (git diff --name-only HEAD..master | grep -f private_files | while read f; do git reset HEAD -- "$f"; rm -f "$f"; done; git commit -m "Merge master, excluding private files.")' 

luego editar el archivo private_files y añadir patrones de ficheros que son privadas; por ejemplo secret_file.*$. Puede reemplazar private_files en el alias con "$(git rev-parse --show-toplevel)"/private_files para leer private_files en el directorio de nivel superior.

Usa git merge-master-exclude-private para hacer la combinación. Esto ejecutará una fusión sin avance rápido sin cometer, encontrará archivos que coincidan con los patrones en el archivo private_files, reset el índice de cualquier archivo privado encontrado, elimine los archivos privados en el directorio de trabajo y luego confirme. Esto debería manejar los archivos que tienen espacios en blanco en sus nombres.

Si no desea realizar la confirmación, dándole la oportunidad de editar el mensaje de confirmación, elimine -m "Merge master, excluding private files." del alias.

0

Sé que esto deja de lado la cuestión, pero simplemente tendría dos repositorios de git. Luego puede agregarlos permanentemente a la lista de ignorar en el repositorio público.

Puede tener un segundo repositorio para los archivos privados y un pequeño script para copiar los cambios en la ubicación correcta en el sistema de producción, al realizar su implementación.

Esto reduce el riesgo de que cuando se vaya de vacaciones y el nuevo pasante actualice el repositorio público, su información privada se filtre accidentalmente. ;-)

2

Un tipo llamado David Albert escribió a tool called Junk para resolver casi exactamente este problema. Permite que los archivos de un repositorio de "cajones de basura" por separado vivan junto a los que están en su repositorio principal.

Los archivos privados tendrán confirmaciones separadas de las públicas, pero podría hacer el trabajo.

0

Parece que se puede usar mine.

Básicamente, se le dice a Git mantenerse al margen de las cosas siguiendo la convención <file or directory>_mine_ y la propia herramienta le da una snapshot, clean y restore función, no de versiones de pleno derecho, pero para cosas personales que hace el truco muy bien.

Todo es pretty concise.

Cuestiones relacionadas