2010-04-28 11 views
15

¿es posible volver a establecer una base de una rama con todas sus subramas en git?git rama rebase con todas las subfunciones

menudo utilizo ramas como etiquetas rápidas/mutables para marcar ciertas confirmaciones.

* master 
* 
* featureA-finished 
* 
* origin/master 

ahora quiero rebase -imaster en origin/master, para cambiar/reformular el commit featureA-finished^

después git rebase -i --onto origin/master origin/master master, Básicamente quiero la historia sea:

* master 
* 
* featureA-finished 
* (changed/reworded) 
* origin/master 

pero lo que se ve es :

hay una forma de evitarlo, ¿o estoy atascado con la recreación de las ramas en los nuevos commit rebasados?

+0

En lugar de las ramas, puedes usar 'git notes' para marcar tus confirmaciones, es decir, las que se copian automáticamente durante las rebases, creo. (Es una función nueva, por lo que necesitará la versión más reciente) http://www.kernel.org/pub/software/scm/git/docs/git-notes.html – Cascabel

+0

Vea también [cómo haría una nueva versión de un subhistoria completa: varias ramas, con algunos enlaces entre ellas resultantes de la fusión] (http://stackoverflow.com/a/9706495/94687). La parte desagradable de esa solución es la necesidad de restablecer las referencias de rama de tema a las nuevas confirmaciones reordenadas luego. –

Respuesta

2

No estoy seguro exactamente cómo llegó allí, pero:

git branch -f (same changeset as featureA-finished) 

debería ser suficiente para restablecer la rama featureA-finished con la historia derecha.

+0

sí, eso es lo que quise decir con »recreando las ramas en las nuevas confirmaciones rebasadas«. Sé que es posible de esta manera, pero se vuelve realmente engorroso para tres ramas ya – knittl

+0

@knittl: interesante. Un diagrama de registro más detallado de esas ramas antes y después podría ayudar aquí. – VonC

+0

solo imagina el mismo gráfico con 15 confirmaciones, cada segundo commit siendo featureA-finished, featureB-finished, featureC-finished, etc. – knittl

1

Lo que le aconsejo es volver a establecer el featureA-finished en origin/master primero. Realice el paso de redacción siguiente. Después de eso, rebase master en featureA-finished. Esto te dará el resultado final que deseas.

Tenga en cuenta que necesitará usar -i en ambas rebases, y puede que tenga que eliminar todas las confirmaciones del original featureA-finshed en la segunda base de datos. Si quisiera, podría escribir una secuencia de comandos que eliminaría esto guardando la rama intermedia y usándola como base para una nueva versión --onto de la base de datos. Incluso podría manejar una secuencia de tales 'subramiones' si lo escribió correctamente. Si necesita ayuda, puedo intentar sacar una.

5

De acuerdo con git's Object Model si solo cambia los metadatos de una confirmación (es decir, confirma el mensaje) pero no los datos subyacentes ("árbol (s)"), su hash de árbol permanecerá inalterado.

Además de editar un mensaje de compromiso, también está realizando una rebase, que cambiará los hash de árbol de cada confirmación en su historial, porque los cambios realizados desde origin/master afectarán los archivos en su historial reescrito: lo que significa algunos de los archivos (blobs) a los que apunta su confirmación han cambiado.

Así que no hay una forma a prueba de balas para hacer lo que quiera.

Dicho esto, la edición de una confirmación con rebase -i no suele alterar la marca de tiempo y el autor del compromiso, por lo que podría usar esto para identificar de manera única sus confirmaciones antes y después de una operación de rebase.

Usted tendría que escribir un script que registra toda la rama de la creación de puntos en contra de estos "marca de tiempo: autor" identificador antes de hacer un rebase, y luego encontrar el reescrita se compromete con la misma "marca de tiempo: autor" Identificación y reajustar la ramificarse en él.

Lamentablemente, no tengo tiempo para intentar escribir este script ahora, así que solo puedo desearle la mejor de las suertes.

Editar: Se puede obtener la dirección autor de correo electrónico y la marca de tiempo usando:

$ git log --graph --all --pretty=format:"%h %ae:%ci" 
* 53ca31a [email protected]:2010-06-16 13:50:12 +0100 
* 03dda75 [email protected]:2010-06-16 13:50:11 +0100 
| * a8bb03a [email protected]:2010-06-16 13:49:46 +0100 
| * b93e59d [email protected]:2010-06-16 13:49:44 +0100 
|/ 
* d4214a2 robert.m[email protected]:2010-06-16 13:49:41 +0100 

Y se puede obtener una lista de las ramas para cada uno de ellos sobre la base de su picadillo de comprometerse:

$ git branch --contains 03dda75 
* testbranch 

¡Cuidado con múltiples ramas por commit, el ancestro común d4214a2 pertenece a ambas ramas!

2

parece que esta característica se está convirtiendo lentamente en git. rebase obtendrá la opción --rebase-refs que hará exactamente lo que me pidió la respuesta original. para la serie de parches propuesta, vea el hilo rebase: command "ref" and options --rewrite-{refs,heads,tags} en gmane.

+0

Es una lástima que esto no parece haber llegado a Git: no he visto tal característica en la documentación actual (página de manual) para git-rebase! (git-1.7.9.3) –