¿Cómo manejo dos bases de código separadas pero muy similares con git / github?

¿Cuál es el mejor método para manejar dos bases de código separadas, pero muy similares en git y git-hub?

Fondo

Tengo un repository de git para un pequeño proyecto de script de shell. Solo tiene 2 o 3 files de código y a menudo trabajo en un solo file. Aunque originalmente hice que el proyecto cumpliera un objective específico mío, lo escribo para que sea más útil en general para otros. Escribo la versión general del caso de uso y luego la modifico para que sea específica para mi objective específico. En la versión específica, podría modificar variables, poner una contraseña, cambiar el order de algunos de los códigos, sacar un bucle for … lo que sea.

¿Qué he intentado?

He intentado con dos methods diferentes y ninguno funciona tan bien como podría pensar que podría:

  1. Dos repositorys separados
    • Problema: código modificado en uno, no se puede fusionar fácil y selectivamente a otro
  2. Dos sucursales en un repo
    • Problema: las sucursales están destinadas a fusionarse eventualmente. No me refiero a fusionar estos elementos nuevamente, sino a fusionar partes del código de manera selectiva.
    • Problema: descubrí que al tratar de usar commands de fusión entre las twigs, era muy fácil confundir qué código en qué twig se estaba fusionando. De alguna manera, fusioné el código entre los dos que era completamente involuntario y no había ninguna indicación sobre la fusión incorrecta hasta que miré el contenido de los files en ambas twigs

También vi Cómo fusionar dos bases de código separadas, pero similares, en un representante de SVN. eso es sobre SVN. Es difícil para mí seguir ya que no sé SVN. Aunque creo que es una pregunta diferente, porque él no está tratando de hacer pública una versión de este código.

Casos de uso que quiero resolver

Específicamente, el problema sale a la luz cuando:

  • Sincronización de comentarios: estoy preparando mi versión especializada y me doy count de que podría agregar un comentario explicativo al final de una línea. Lo agrego, pero el comentario ahora no está en la versión generalizada.
  • Cosas que no quiero compartir: estoy preparando mi versión especializada y agrego una contraseña o cambio el order de cómo se realizan las operaciones. NO QUIERO que estos cambios vayan a la versión generalizada.
  • Mismo file: los dos cambios anteriores a menudo estarán en el mismo file, lo que dificulta la fusión de elementos. Hay fusiones interactivas, pero no sé si la interacción se puede hacer en un solo file.
  • General -> Especializado – Yo u otra persona podría actualizar la versión generalizada para tener nuevos contenidos o comentarios que también sería útil tener en mi versión especializada. Quiero traer esto de general -> especializado, sin jugar con ninguna otra diferencia de código en la versión especializada.

Git vs Github

En general, mi pregunta es cómo hacerlo dentro de los confines de git. Sin embargo, puede tener implicaciones sobre cómo interactuar con github también. Mi versión generalizada está en github. La versión especializada NO debe estar activa en github. Creo que el método de mi twig anterior no empujaba ambas twigs si tenía cuidado … pero siempre estaba inseguro. De cualquier manera, la solución debería permitir que exista una versión que sea pública, y una versión que se mantenga localmente … incluso si es un poco compleja o requiere atención.

Esto se puede hacer fácilmente con dos twigs. No estoy seguro de por qué dices "código modificado en uno, no se puede fusionar fácil y selectivamente con otro", porque la fusión es bastante fácil en Git.

La estructura que sugeriría es tener una sucursal para su versión general y una sucursal para su versión personal. Las fusiones solo deberían ocurrir en una sola dirección, desde la twig general hasta la twig personal. Esto significa que cualquier cambio que realice en la versión general se incorporará a la versión personal.

En otras palabras, esto está bien …

git checkout personal git merge general 

Esto que nunca debes hacer …

 git checkout general git merge personal 

Si realiza un cambio en su versión personal y decide que sería fantástico tener ese mismo código en la versión general, debería ser capaz de manejarlo con bastante facilidad con una selección inteligente. Solo tomará un poco de previsión organizar los commits en la twig personal. Necesitará una confirmación en la sucursal personal que contenga solo los cambios que desea llevar a la versión general, luego simplemente selecciónelo en la twig personal y suéltelo en la sucursal general.

Dos repositorys pueden lograr lo mismo. Esto networkinguciría el riesgo de que accidentalmente cargue su versión personal a Github, pero sería más tedioso trabajar con las dos versiones diferentes.

Personalmente, iría con dos sucursales en el mismo repository.

Para evitar empujar su versión especializada a github, establezca la configuration push.default en tracking (o upstream para git> = 1.7.4.2). Ver http://longair.net/blog/2011/02/27/an-asymmetry-between-git-pull-and-git-push/ para los detalles sangrientos.

Las fusiones deberían funcionar igual de bien si usa un repository separado o simplemente una sucursal. Como una respuesta de alto nivel, finalmente vas a tener que ser realmente bueno en la fusión. Mucho de eso vendrá de realmente profundizar en cómo funciona git en un nivel bajo con respecto a la bifurcación, fusión y rebase. A diferencia de otros sistemas de control de versiones, he descubierto que el git requiere una comprensión profunda de sus elementos internos para realmente usarlo correctamente.

En segundo lugar, la idea de utilizar dos twigs : una twig pública para la versión general (que se envía a GitHub) y una twig privada para su código especializado (que no se publica en GitHub). Sin embargo, me gustaría añadir que git stash es una herramienta esencial que te permite hacer lo que quieres hacer en el escenario que describes (estás en el medio de trabajar en la versión personal, y encuentras un cambio en hacerse en la versión general).

De hecho, es una buena práctica implementar siempre cambios generales en la twig general, y luego hacer

 git checkout personal git merge general 

Ahora, puedes usar de forma útil, además, git stash ; tomemos el escenario donde estás actualizando la versión especializada y pensando en un cambio general:

  1. Guarda los cambios actuales en la versión especializada:

     git stash 

    Esto guarda los cambios en comparación con el último compromiso, sin crear un nuevo compromiso. Esto es útil para almacenar su trabajo no confirmado en progreso.

  2. Acude a la sucursal general para hacer el cambio general en el que estaba pensando:

     git checkout general # or master, or whatever name your general branch has 

    Luego puede implementar su modificación general y comprometerla como de costumbre.

  3. Antes de reanudar el trabajo en su versión especializada, importe el cambio general:

     git checkout personal git merge general 

    git es lo suficientemente inteligente como para hacer esto bien: solo se debe hacer la última actualización, generalmente útil, a su código.

  4. Usted reanuda su trabajo en la sucursal especializada importando su trabajo escondido en progreso:

     git stash pop 

¡Eso es todo! La key es usar git stash para save los cambios en el medio de tu trabajo, sin crear un compromiso solo para esto, y luego aplicar tus cambios con git stash pop .

Usa los submodules de git. Si desea mantener una twig separada del submodule, cree una twig en el repository de ese proyecto y conserve todos los cambios localmente en esa twig, y ​​use solo esa twig en la extracción del submodule.

La fusión entre diferentes sets de cambios es algo que necesitarás hacer a medias. Git tiene una gran compatibilidad con la fusión, y si no mantienes las dos twigs demasiado lejos la una de la otra, deberías poder get una intervención manual mínima. github (o cualquier otro proveedor de alojamiento) realmente no tiene nada que ver con nada de esto. Si desea mantener una sucursal privada, no la envíe al repository público. Simple como eso.