¿Cómo separé una gran twig de Git en muchas twigs más pequeñas?

He importado desde SVN a Git, ahora tengo una gran sucursal, así:

  • trabajar en la característica C
  • trabajar en la característica B
  • trabajar en la característica C
  • trabajar en la característica C
  • trabajar en la característica B
  • trabajar en la característica A

Quiero twigs de características separadas, para A, B, C. Estoy seleccionando compromisos para nuevas twigs, pero esto no los quita de la twig original, así que tengo que rastrear manualmente los que he extraído.

Hay alnetworkingedor de 800 compromisos para dividir, y tal vez 50 funciones / correcciones de errores.

Sería bueno tener los que he sacado reflejados de esta manera de alguna manera en el logging de git, entonces sé cuáles ya hice. es posible?

Puedo cambiar la base de toda la sucursal, omitiendo las confirmaciones que he retirado, pero me preocupa que esto genere muchos conflictos. No quiero resolver 500 conflictos cada vez que retiro un commit.

¿Cuál es el mejor método para retirar las confirmaciones de una sucursal de uber en sucursales de funciones más pequeñas, mientras se hace un seguimiento de su progreso?

Solutions Collecting From Web of "¿Cómo separé una gran twig de Git en muchas twigs más pequeñas?"

Lo que hago en este caso es usar rebase interactivo .

En tu HEAD , crea tus twigs A , B y C Cree también una twig de "copy de security" (puede ponerle un nombre de backup ) en caso de que las cosas vayan mal y necesite recuperar su HEAD original.

 git branch feature-a git branch feature-b git branch feature-c git-branch backup-before-rebase 

Luego, crea una twig en la confirmación de la que deseas que comience, tal vez en una confirmación estable conveniente. Llámalo new_trunk o algo así.

 git checkout HEAD~50 ## this will be the new tree-trunk git branch new_trunk 

Luego, realice rebase interactivos y select los commits que desea mantener en esa twig. Usado de esta manera, es básicamente como cherry-pick a granel.

 git checkout feature-a git rebase -i new_trunk ## -i is for "Interactive" 

Cuando hayas terminado, deberías tener 3 sucursales con historiales separados comenzando desde new_trunk y una twig de backup refleje el antiguo HEAD si aún lo necesitas.

Personalmente, realmente consideraría los pros y los contras de estos grandes cambios (una vez más si ya has hecho esto). Si te encuentras con conflictos (que son en gran medida rebase / cherry-pick molestos y difíciles de resolver por sí mismo), probablemente tengas dificultades al fusionar funciones con tu twig "maestra".

¿No sería mejor / más fácil congelar su gran twig, hacerlo "hecho" (o "lo suficientemente bueno") y crear nuevas twigs de características en él? (¿O excluir solo algunas twigs?)

Pero a tu pregunta:

Si desea realizar un seguimiento de los cambios / confirmaciones faltantes, utilice automáticamente el command git cherry.

 git cherry featureBranch bigBranch 

Si no hubo conflictos mientras seleccionas o modificas tu twig de características, puedes usar el código anterior con algunas canalizaciones adicionales:

 git cherry featureBranch bigBranch | awk '{ print "pick " $2 }' | tee remaining 

Esto imprimirá (y lo saveá en el file llamado "restante") confirma que falta en featureBranch. Puede agregar esto a la database interactiva en bigBranch para descartar las confirmaciones que ya no desea. (Tal vez pueda guionizarlo aún más con el editor "ed" como editor de git y pasar commands a la input estándar de rebase interactivo, pero no lo intenté).

Solo para simplificar la respuesta de Willoller ,

hacer las twigs de características, y copy de security, en el caso

 git branch feature-a git branch feature-b git branch feature-c git branch backup-before-rebase 

luego revisa una twig de características y realiza una rebase interactiva a partir de la confirmación de la que deseas que empiece

 git checkout feature-a git rebase -i <safecommit> enter code here 

Si desea que algunas twigs de características compartan algunas confirmaciones para mantener su tree limpio, no cree la twig de características posterior al inicio, sino una vez que tenga una twig de características rebasada y luego use la reference de compromiso compartido como su próximo compromiso de security.

 #on branch feature-a git checkout -b feature-d git rebase -i <shanetworkingcommit> 

Otro método que acabo de descubrir es el uso de "notas git".

http://alblue.bandlem.com/2011/11/git-tip-of-week-git-notes.html

Esta característica permite agregar comentarios a las confirmaciones existentes sin cambiar la twig / requerir una rebase. Un método para rastrear los commits que se han eliminado es agregar una nota git a cada uno:

Cherry-picked to features\xyz 925a5239d4fbcf7ad7cd656020793f83275ef45b

Esto podría ayudar en un process en gran parte manual: podría escribir un pequeño guión para seleccionar una confirmación en una twig en particular y luego agregar la nota de git relevante a la confirmación original.

Alternativamente, si quieres ser realmente original, puedes automatizar todo el process, de la siguiente manera:

  1. Agregue una nota de git a cada confirmación, diciendo qué twig de function quiere que TOCHERRYPICK: features\xyz
  2. Escriba un script para escanear todas las notas de git, y cree automáticamente todas las twigs de características y select las confirmaciones seleccionadas correctas. Luego podría cambiar la nota de git a CHERRYPICKED: features\xxx at 925a5239d4fbcf7ad7cd656020793f83275ef45b para permitir que la herramienta se vuelva a ejecutar más tarde para seleccionar más commits.
  3. Si realmente desea resaltarlo cuando se ha seleccionado una confirmación, también puede automatizar la creación de una label con un nombre similar: CHERRYPICKED:<branch>:SHA

Honestamente, no haría esto a less que tenga una gran list de confirmaciones que deben dividirse y que son características muy independientes, es decir, que no se altera la misma línea donde habría conflictos para resolver.

Como otros han sugerido, cree una nueva twig para cada característica y use git rebase --interactive para include los commits deseados.

Para asegurarse de que ninguno vaya por mal path, cree los contenidos de los files git-rebase-todo por

  • editar una list de todas las confirmaciones deseadas y clasificarlas por características
  • separando la list de commits en files separados

Puede crear la list de confirmaciones usando un command como

 git log --oneline --reverse 44e19^... > log.txt 

para mostrar commit 44e19 en adelante. Esto te dará un file como este

 44e1936 dSRGratuities (SummaryRecord) 67fedda Receipt Report HEADER: 20! multiply by Paym_FieldCount 69d70e2 Receipt Report: Payment .... 

que cuando se sorted.txt podría parecerse a mi sorted.txt

 c 44e1936 dSRGratuities (SummaryRecord) a 67fedda Receipt Report HEADER: 20! multiply by Paym_FieldCount b 69d70e2 Receipt Report: Payment c abea7db Receipt Report: Cashback a cf96185 Receipt Report: Gratuity c 70e987a Receipt Report: use amount tendenetworking for printing a 7722ac8 Receipt Report: use amount tendenetworking for calculations c 47f1754 Receipt Report: store amount tendenetworking b b69a73f Receipt Report: Use enum Paym_FieldCount a 9a0b471 Receipt Report HEADER: enum PaymentEntries (with Paym_FieldCount) c ad67e79 Use SharpReport enum b 3c510c6 enum SharpReport a e470e07 m_Gratuities m_dSSGratuities (SalesSummary) b 4e0c3e4 m_Gratuities m_szGratuities (SalesSummaryRecord) b bd054f7 _gx_fn_Cashback 

Luego, escriba en su lenguaje de scripting favorito para convertir la list orderada en una colección de files git-rebase-todo . Tu script podría parecerse al que acabo de escribir.

 foreachline text sorted.txt { set fields [split $text { }] set branch [lindex $fields 0] set commit [lindex $fields 1] set comment [string range $text 10 end] set command "echo pick $commit $comment" exec cmd /S /C $command >> $branch.txt } 

El script lee el file de orderación de compromiso línea por línea y se divide por un carácter de espacio {} para get los dos campos de branch y commit , y toma una subcadena (caracteres 10 en adelante) para una descripción del compromiso. La descripción no es obligatoria, pero es útil para nosotros, los humanos, verificar los errores.

A continuación, coloca una línea en el file apropiado git-rebase-todo , creando un file por function. Lo pirateé ejecutando un command muy feo de Windows echo string >> file .

Esto crea una cantidad de files, por ej. Mi file a.txt

 pick 67fedda Receipt Report HEADER: 20! multiply by Paym_FieldCount pick cf96185 Receipt Report: Gratuity pick 7722ac8 Receipt Report: use amount tendenetworking for calculations pick 9a0b471 Receipt Report HEADER: enum PaymentEntries (with Paym_FieldCount) pick e470e07 m_Gratuities m_dSSGratuities (SalesSummary) 

Todo es feo No lo recomiendo a less que tengas que hacerlo y seas bueno escribiendo guiones.