2010-11-11 15 views
8

Tengo la siguiente situación: Realicé algunas confirmaciones en mi repositorio local, y luego una gran fusión de otra rama (~ 150 confirmaciones) en el maestro: tenía muchos conflictos.¿Cómo uso git rebase -i después de la fusión de git sin estropear las cosas?

Ahora, quiero mover una confirmación que hice antes de la fusión para que esté antes de presionar.

Normalmente, usaría "rebase -i" para ello.

Desafortunadamente, el comportamiento predeterminado es romper el commit de fusión única que hice, que realmente agregó 150 commits más para dominar en commits separados (entiendo que es como si quisiera usar rebase en lugar de merge para comenzar), que es un mal comportamiento para mí por varias razones.

Descubrí el indicador '-p' para rebase, que conserva las fusiones, y estaba muy contento con él. Lamentablemente, esto de hecho aplica la misma fusión otra vez, y olvidé todo sobre mi trabajo duro en la resolución de conflictos. De nuevo, ¡mal comportamiento!

¿Hay una solución para lo que quiero? ¿Usar rebase -i después de combinar para reordenar o editar confirmaciones específicas sin tener que repetir mis operaciones posteriores a la fusión?

Gracias!

+2

¿Has echado un vistazo a [git rerere] (http://www.kernel.org/pub/software/scm/git/docs/git-rerere.html)? –

+2

'git rerere' no puede ayudarte ahora, ya que registra la resolución del conflicto cuando comprometes la fusión ... excepto que hay un script llamado [rerere-train.sh] (http://git.kernel.org/? p = git/git.git; a = blob; f = contrib/rerere-train.sh; hb = HEAD) en el directorio contrib de git que "ceba" la base de datos de datos desde las asignaciones de fusión que ya ha realizado. – Cascabel

Respuesta

13

Esto es lo que el script rerere-train.sh que mencioné en mi comentario hace - esencialmente rehace la fusión, usa su resolución, y simplemente le permite volver a verla. Usted puede hacer esto manualmente sólo para su única confirmación si te gusta:

git checkout <parent of merge commit> 
git merge <merged commit>   # if this goes cleanly, we're done 
git rerere      # done automatically if rerere.enabled is true 
git checkout <merge commit> -- . # check out the files from the result of the merge 
git rerere      # done automatically if rerere.enabled is true 
git reset --hard     # wipe away the merge 

# and you'd want to follow with git checkout <branch> to return to where you were 

Pero también se puede configurar simplemente rerere.enabled de verdad, y hacer esos pasos menos las llamadas directas a git rerere - y que estaría ubicado en el En el futuro, se ejecutará automáticamente cada vez que resuelva conflictos. Esto es lo que hago - es increíble.

Si desea ejecutar el script directamente, es probable que desee ejecutarlo con argumentos como rerere-train.sh ^<commit before the merge> <current branch>. (La notación significa ^commit "no caminar más allá de esto en la historia", por lo que no se molestará en hacer esto durante toda la fusión se compromete en su repositorio.)

Sin embargo se obtiene rerere a hacer su cosa, Deberías terminar con la resolución deseada registrada. Eso significa que puede seguir adelante y hacer su rebase -i, y cuando se encuentre con el conflicto, volverá a REUSE la RE-resolución resuelta. Solo un aviso: aún deja los archivos marcados como conflictivos en el índice, para que pueda inspeccionarlos y asegurarse de que lo que hizo tenga sentido. Una vez que lo haga, use git add para verificarlos como si hubiera resuelto los conflictos usted mismo, ¡y continúe como siempre!

El git-rerere manpage contiene una muy buena y larga descripción del uso normal de rerere, que no implica nunca llamar a rerere, todo se hace automáticamente. Y una nota que no enfatiza: está basada en conflictos, por lo que puede reutilizar una resolución incluso si el conflicto termina en un lugar completamente diferente, siempre y cuando siga siendo el mismo conflicto textual.

+0

¡Guau, esto parece serio git-fu! – Benjol

+0

@Benjol: ¡La resolución de conflictos es un asunto serio! (Pero no es realmente aterrador, simplemente habilite la repetición en la configuración y permita que ocurra la magia). – Cascabel

+0

La página de manual de git-rerere vinculada ahora es 404 Not Found. – Jez

1

He hecho una secuencia de comandos para hacer esto here. Consulte el open issues para conocer las limitaciones conocidas.

Primero tendrá que instalar rerere-train.sh en su RUTA.En Fedora esto se puede hacer con:

install "$(rpm -ql git|grep '/rerere-train.sh$')" ~/bin 
0

Solía ​​rerere-train.sh de usuario @ respuesta de Jefromi. Sin embargo tuve este error:

$ ../rerere-train.sh HEAD 
C:\Program Files\Git\mingw64/libexec/git-core/git-sh-setup: line 6: .: git-sh-i18n: file not found 

De esta http://kernel.opensuse.org/cgit/kernel-source/commit/?h=linux-next&id=d52b9f00588bb18d7f7a0e043eea15e6c27ec40c vi esto:

Michal Marek

The git-sh-setup helper has apparently never been meant to be used by scripts outside of git. This became apparent with git 2.10:

Después downloading an older version - 2.3.4 Portable - logré hacer rerere-train.sh trabajo.