remota - git push example
Git fusionar calabaza repetidamente (5)
Empezando con
X stable
/
a---b---c---d---e---f---g development
Puede usar los siguientes pasos para copiar la última confirmación desde su rama de desarrollo a su rama estable:
git checkout development@{0} # get working tree from "development", detach HEAD
git reset --soft stable # reposition detached HEAD on "stable"
git commit # enter the appropriate commit message
git branch temp # create a temporary branch "temp" at HEAD
git checkout temp # get on the new temporary branch
git branch -M stable # rename "temp" to "stable"
entonces terminas con:
X-------------------G stable
/
a---b---c---d---e---f---g development
Si continúa trabajando en "desarrollo", por ejemplo,
X-------------------G stable
/
a---b---c---d---e---f---g---h---i---j development
puedes repetir los mismos comandos de git que antes y terminarás con:
X-------------------G-----------J stable
/
a---b---c---d---e---f---g---h---i---j development
Estoy tratando de tener dos ramas con archivos binarios en git: un "desarrollo" y uno "estable". La rama de desarrollo puede tener varios cambios de estos archivos antes de que quiera "liberarlos" a la rama estable (y la rama estable tiene esos archivos renombrados, en caso de que sea relevante).
Podría hacer una fusión normal, esto funciona bien, pero conserva demasiada historia: al tirar de la rama "estable", todos los compromisos intermedios de la rama de "desarrollo" también se extraen (porque son compromisos de los padres). Pero estamos hablando de archivos binarios que no tienen ninguna estrategia de fusión razonable (excepto la suya / la nuestra), por lo que el historial real de los archivos en la rama de desarrollo es inútil. Cuando saco la rama "estable", obtengo esto:
X-------------------G stable / / a---b---c---d---e---f---g development
Como G tiene un padre en la rama de desarrollo, obtengo toda la historia de la rama de desarrollo (objetos de datos para c, d, e, fyg) en mi repositorio, lo que no me interesa (X es lo mismo que b, con algún cambio de nombre de archivo aplicado).
Así que traté de hacer git merge --squash
cambio de la rama de desarrollo a la rama estable. La primera fusión y confirmación se realizó correctamente, los resultados fueron los esperados (buen registro de cambios en el mensaje de confirmación, sin relación con la rama de desarrollo):
X-------------------G stable / a---b---c---d---e---f---g development
Después de extraer esta rama estable aplastada, obtengo esto en mi repositorio, que es lo que quiero:
a---b---X---G
Pero la segunda fusión falló (porque git no tenía forma de saber cuánto me fusioné y me confundí).
- ¿Es posible grabar la fusión de alguna manera, sin producir un "commit de fusión" con dos padres?
- O, ¿es posible decirle a git que combine solo un cierto "rango" de revisiones, como en SVN?
- O bien, ¿es posible realizar una combinación normal sin tener que descargar todas las referencias de la otra rama al tirar?
- ¿O debería proporcionar un controlador de combinación personalizado para los archivos en cuestión, que simplemente cambia el nombre de "su" versión a "nuestro", resolviendo así los conflictos? Todavía tengo miedo de que
--squash
siempre intente fusionar toda la historia, hasta el padre común, resolviendo solo la mitad de mi problema.
Actualización: rebase
Si entiendo el rebase correcto, terminaré con esto:
X stable / a---b---c---d---e---f---g development
Lo cual me proporciona todos los datos que no me interesan (c, d, e, f) y como extra, perderé la información de que b era una versión estable en la sucursal.
Cada revisión de desarrollo agrega alrededor de 5MB al tamaño del repositorio (y reempaquetar todo el repositorio lo reduce solo alrededor del 10%), la rama "estable" es casi gratuita (los datos ya están allí). Quiero sacar una nueva revisión de la rama estable para extraer solo los 5MB nuevos, pero en cambio actualizar de X a G descarga 25MB, porque de alguna manera no puedo decir que no me importan los contenidos de c, d , e y f.
Soy nuevo en git, pero parece que --squash es lo que quieres, solo necesitas manejar la rama de manera diferente.
$ git merge --squash development
$ git branch -d development
$ git checkout -b development
# continue work on development branch
Esto esencialmente truncaría la historia de la rama de desarrollo, y la siguiente fusión sería solo lo que usted quería. Al mirar la página man, parece que el desarrollo de git branch -f development
podría hacer lo mismo que eliminar y volver a crear la rama.
Como dije, soy bastante nuevo en git, así que me gustaría recibir algunos comentarios sobre esta idea.
La respuesta más votado efectivamente diferencia las ramas estable y de desarrollo y aplica todos los cambios que faltan en el establo al comprometerse. Hay una manera alternativa de hacer esto:
$ git checkout stable
$ git diff stable development | git apply --index -
$ git commit
Antes de comprometerse, puede revisar los archivos por etapas. Si desea cancelar el proceso después de aplicar el diff, puede usar comandos básicos para eliminar los cambios del índice y del directorio de trabajo.
$ git reset --hard
Puede repetir el proceso muchas veces, ya que en realidad solo está difiriendo las puntas de ambas ramas cada vez que necesita fusionarse.
Tenga en cuenta que hay una suposición aquí que también se aplica a la otra respuesta: no hay commits en la rama estable que no sean los que provienen de la rama de desarrollo . Si la misma línea se cambiara independientemente en ambas ramas, a diferencia de una combinación regular, este enfoque no le daría un conflicto. En cambio, simplemente anularía los cambios en la rama estable con los que están en desarrollo.
Si le preocupa esto, cada vez que se comprometa con estable, puede poner el rango de hash de consolidación de desarrollo combinado en el mensaje de confirmación. De esa forma, tienes algún registro, si alguna vez necesitas dar marcha atrás.
Este no es el lugar correcto para usar merge --squash
. Un buen lugar para usarlo es en una rama de tema descartable, que se fusionará en su rama principal y luego se deshará. Todo el desarrollo realizado en la rama de tema se muestra como uno comprometido en la rama principal. En su situación, debería fusionarse desde la rama de desarrollo normalmente, y luego usar git-rebase --interactive
para aplastar las confirmaciones que desee.
¿Es posible grabar la fusión de alguna manera, sin producir un "commit de fusión" con dos padres?
Si entiendo la pregunta correctamente, no. Absolutamente no .
¿Es posible decirle a git que combine solo un cierto "rango" de revisiones, como en SVN?
Sí. git merge [commit hash]
O bien, ¿es posible realizar una combinación normal sin tener que descargar todas las referencias de la otra rama al tirar?
Ver la respuesta a la pregunta anterior.
¿O debería proporcionar un controlador de combinación personalizado para los archivos en cuestión, que simplemente cambia el nombre de "su" versión a "nuestro", resolviendo así los conflictos? Todavía tengo miedo de que --squash siempre intente fusionar toda la historia, hasta el padre común, resolviendo solo la mitad de mi problema.
¡No! Simplemente no use git merge --squash
. ¡Este no es el lugar correcto para usarlo!
puede usar git rebase -i
(modo interactivo) para sqash todos sus cambios, simplemente cambie las líneas a m
o meld
(actualización: para versiones más nuevas de Git escriba s
o squash
)
usted tendrá un único compromiso que podrá fusionar. si quieres que cada paso del tuyo sea reservado, debes crear otra rama en tu rama de piratería antes de hacer la rebase, esto se puede hacer con la git branch small-dirty-changes-i-don''t-want-anybody-to-see
todo esto tiene que hacerse antes de intentar fusionar; paso a paso:
# on branch "hacking": hack commit hack commit hack commit
# create a reference to your history
$ git branch dirty-history
# sqash your commits by setting all lines to "meld"
$ git rebase -i
# checkout master or the branch you want to merge to
$ git checkout master
# merge your squashed commit
$ git merge hacking
# or: $ git pull hacking