2009-09-25 12 views
5

He estado investigando a través de git merge y rebase docs, y algo no se está hundiendo. Estoy trabajando activamente en un proyecto en Git, y necesito compartir hitos específicos con otros desarrolladores. Quiero compartir el código exactamente como está en cada hito/lanzamiento, pero no todos mis compromisos pequeños previos a cada lanzamiento.Git rebase/merge para publicaciones públicas

¿Cómo creo una rama de versión que refleje una rama de desarrollo, donde cada una de las confirmaciones en la rama de versión contiene varias confirmaciones de la rama de desarrollo? En otras palabras, la rama de publicación debe tener un historial comprimido, pero debe coincidir con la rama de desarrollo.

Originalmente, había pensado que usar una rama separada y usar git merge --squash sería efectivo, creando una nueva rama con una serie de confirmaciones que reflejaran el conjunto completo de cambios entre cada versión. Ahora entiendo que git merge --squash no funciona para usos repetidos.

Git rebase funciona para colapsar varias confirmaciones en una confirmación grande, pero como cambia el historial de confirmaciones, ¿no cambiaría mi historial privado así como las publicaciones públicas?

No quiero perder mi historial de pequeños cambios, pero quiero enviar confirmaciones combinadas a un servidor compartido.

Respuesta

7

Seguramente, si sus compromisos son dignos de mantener y constituyen su trabajo para un lanzamiento al público, entonces ¿deberían formar parte de su historial publicado? Si no desea publicar su historial completo de repositorios, es mejor que use git archive para crear archivos de lanzamiento.

Dicho esto, si realmente desea crear una rama de publicación con un historial separado, entonces es posible. Sin embargo, se está preparando para una mayor sobrecarga de mantenimiento, ya que nunca podrá fusionar su historial privado con su sucursal de publicación pública, ya que eso traería todo el historial privado a su sucursal de publicación. Esto es lo que hace Git; rastrea de dónde vienen los cambios.

Puede fusionarse desde la rama de publicación a la rama privada, pero como su trabajo (presumiblemente) proviene de la rama privada, esto no le hará ganar mucho. La opción más fácil es tener una rama de publicación separada que contenga solo las confirmaciones de instantáneas del estado de la sucursal privada en los puntos de publicación.

Suponiendo que ha llegado al punto en el que desea crear una confirmación en la rama de publicación (release) basado en la confirmación actual en la rama privada (private) y suponiendo que tiene el árbol liberado no hay cambios en el índice, esto es lo que puede hacer.

# Low-level plumbing command to switch branches without checking anything out 
# (Note: it doesn't matter if this branch hasn't yet been created.) 
git symbolic-ref HEAD refs/heads/release 

# Create a new commit based on the current index in the release branch 
git commit -m "Public release commit" 

# Switch back to the private branch 
git checkout private 

Usted puede hacer esto para cada versión (o sub-release) y el nuevo compromiso será construido directamente sobre la parte superior de la versión anterior sin incorporar ninguna de su historia privada.

+0

Eso ciertamente lo hace. Funcionó para mí :) –

+0

Gracias, Charles. Eso hace lo que estoy buscando. – Neil

2

Solo crea una nueva rama y haz todo el aplastamiento allí. Luego publica eso. Tus commits más pequeños seguirán allí en las otras ramas.

Mi flujo de trabajo para esto sería algo como esto:

git co -b release_branch_squash release_branch_with_all_commits 

git rebase last_release_tag 

Ahora es el momento para hacer frente a todos los conflictos que puedan surgir. Realmente no sé cómo evitar esto. Por lo general, no es un gran problema. Mi repositorio git ya ha registrado la mayoría de las resoluciones de conflictos de todos modos.

git rebase --interactive last_release_tag 

Esto abrirá vim. Para todo el lanzamiento que deseo aplastar, reemplace pick con squash. Entonces solo guarde y salga. Hecho.

+0

¿Puedes elaborar? De los comentarios como http://stackoverflow.com/questions/1464642/git-merge-squash-repeatedly/1465119#1465119 parece que la fusión repetida --squash no va a funcionar. Cuando lo he intentado, recibo listas muy largas de conflictos, aunque los archivos tienen una historia común. Si entiendo correctamente, git merge --squash crea una nueva confirmación que no comparte el historial de las confirmaciones anteriores, por lo que las fusiones futuras no tienen antepasados ​​comunes. Has descrito el comportamiento que quiero, pero estoy tropezando con conseguir que Git lo haga. – Neil

+0

He actualizado la respuesta con mi flujo de trabajo propuesto. Aunque debo admitir que la solución de Charles Bayleys podría ser más adecuada para sus necesidades. – davrieb

Cuestiones relacionadas