¿Cómo get diagtwigs de twigs más útiles en git?

A veces me cuesta tratar de ver qué estaba sucediendo en la historia de los repositorys de git, incluso con grandes herramientas como SourceTree, los diagtwigs de las twigs pueden ser confusos. El problema principal para mí es que no puedo decir en qué twigs se realizaron algunas confirmaciones, y la cadena de confirmaciones en una sola twig a menudo se muestra en diferentes líneas visuales a medida que aumenta y disminuye el número de twigs simultáneas y las personas que trabajan en las twigs. .

Mis pensamientos iniciales estaban en la línea de "¿Y si git almacenara el nombre de la twig en el que se realizó una confirmación? Entonces, los generadores de diagtwigs podrían agrupar esos compromisos en la misma línea". Esta pregunta: ¿Por qué Git no almacena el nombre de la twig como parte de la confirmación? pregunta lo mismo (pero por diferentes razones) y después de leerlo y algunos otros enlaces me di count de que simplemente almacenar el nombre de la sucursal no resolvería mi problema de todos modos. Por ejemplo, cuando varias personas hacen confirmaciones alternas en sus sucursales locales con el mismo nombre de sucursal, tratar de mostrarlas en la misma línea sería técnicamente incorrecto.

De todos modos, así sucesivamente a mis preguntas …

  1. ¿Existe actualmente una forma de inferir la estructura de bifurcación histórica correcta y producir un diagtwig de aspecto agradable, tal vez buscando los posts de confirmación de estilo "merge master into branchX"?
  2. ¿Existe un caso válido para una característica dentro de git que ayude a preservar parte de la información del flujo de trabajo (es decir, context bajo el cual se realizó ese trabajo), o ya es posible y lo estoy haciendo todo mal?

En cuanto a la pregunta 2: estaba pensando quizás algo así como un llamado "work-stream". Al crear una twig, puede proporcionar opcionalmente un nombre de flujo de trabajo (o "henetworkingar" del nombre de la secuencia de trabajo de la twig actual), y al cambiar de twig, la stream de trabajo actual también cambiará. Por lo tanto, cada compromiso se haría en el context de un flujo de trabajo y esta información podría almacenarse en el compromiso o como metadatos separados en el repository de git. Realmente no sé sobre el funcionamiento interno de git así que puede haber otras / mejores maneras de lograr esto. Los diagtwigs de twigs podrían hacer algo visualmente obvio (como un color de background diferente) para ayudar a ver cómo fluían las cadenas de compromiso entre diferentes flujos de trabajo.

Tenga en count que git es el autoproclamado "rastreador de contenido estúpido". No quiere ser más inteligente de lo que debe ser, porque esto lo mantiene muy flexible y, por lo tanto, muy poderoso. Los propios compromisos son solo files de text, y nada más que eso. Literalmente se ven así:

tree 68cd5b298858425fd8b5c2c0adfa62249b4eb650 parent c9ac0bb0d74d59b1ccb5aa8c498c33314b16948e author aperson <aperson@somecompany.com> 1368010332 -0700 committer aperson <aperson@somecompany.com> 1368010332 -0700 Add test module for widget.py 

tree apunta al file de text hash que enumera los contenidos de la carpeta del proyecto, y esta list puede contener otros treees, recursivamente y blob , que son contenidos hash de files. parent es solo el hash de otro commit, que una vez más, es solo otro file de text como este. Las líneas de autor y committer también tienen marcas de time Unix con compensaciones GMT. El rest del file es el post de confirmación. Un commit – el file de text – responde a las 5 meta preguntas sobre sí mismo: quién (autor / committer), qué (puntero al tree), cuándo (timestamps), dónde (parent commit (s)), y por qué (commit message) . tree y parent (padre puede ser más de una línea de padres para representar compromisos de fusión) son pointers. Dicen "ese tree describe la instantánea de este compromiso" y "ese compromiso / esos compromisos es / son de dónde vino".

En teoría, podría mantener el nombre de la sucursal, pero las twigs también son solo pointers. Si estás en la twig principal, hay un file de text llamado master en .git/refs/heads que contiene el hash (es decir, el número de 40 dígitos) que nombra la confirmación en la que te encuentras actualmente. El hecho de que esté en esa twig (también llamada "cabeza") es solo una línea en el file de text .git/HEAD , también un puntero, que dice ref: refs/heads/master , que solo apunta al master nombre de file en la carpeta heads bajo refs . Todo son solo consejos, pero lo más importante, todo es muy fluido.

Git quiere ser demasiado tonto para que las twigs importen. En qué twig se creó inicialmente una confirmación no es realmente útil, o quizás mejor dicho, es algo demasiado inestable para tratar de que sea útil, ya que puede mover compromisos a su gusto. Lo he hecho a menudo para get cosas como las quiero.

Me di count de que estaba haciendo mixedbranch generales y muy específicas de proyectos en una twig de proyecto, llamémosla twig mixedbranch , y que las cosas del proyecto merecían ser su propia twig, por lo que realicé una nueva installation interactiva para descomprimirlas. Es decir, hice git branch projectname para agregar un segundo encabezado apuntando al mismo compromiso al que mixedbranch (pero no mixedbranch a él), luego hice git rebase -i <commit before I started mixing things> . Luego, en el editor de text que apareció, eliminé todas las líneas de confirmación específicas del proyecto, las guardé y salí. Esto reconstruyó la twig con el nombre actual, pero sin los commits basados ​​en proyectos (es bueno mantener los commits lo suficientemente detallados para permitir esto fácilmente, por varias razones más allá de esto).

Luego hice el nombre de proyecto de git checkout projectname para cambiar a la nueva cabecera de twig, que todavía tenía position en la punta de todas esas confirmaciones mixtas, e hice lo mismo en reversa – git rebase -i <that same old commit before the mixing occurnetworking> , pero esta vez eliminó las líneas específicas que no son de proyecto . Esto reconstruyó la nueva bifurcación utilizando las confirmaciones de bifurcaciones originales, sin las confirmaciones fuera del proyecto y el nombre de proyecto señalado a la cabeza recién renovada. Ahora que ninguna de las twigs apuntó al set original entrelazado de confirmaciones, todas desaparecieron de la vista, y parecía que aabbabbaba<--mixed había convertido simplemente en aaaa<--nonmixed y bbbbb<--project . Almacenar en qué twigs se había creado originalmente podría ser un desastre. Es algo demasiado "inteligente" para ser confiable, así que git – "el rastreador de contenido estúpido" – ni siquiera lo intenta.

En términos de seguir el path de las confirmaciones en las sucursales, todo esto se hace al revés, porque los commits (esos files de text) simplemente almacenan references a sus padres. Solo puedes descubrir el linaje en el pasado. Cuando se fusiona, crea una nueva confirmación, que es solo una instantánea de todo el tree fusionado. La twig en la que se encuentra actualmente (o se está fusionando) se considera el primer padre y la twig que se fusiona es la segunda. Si hay otras twigs fusionadas también, serían el tercero, el cuarto, etc. De esta forma, git puede seguir fácilmente los commits primarios para hacer un seguimiento de, e indicar visualmente, qué confirmaciones fueron, por ejemplo, twig principal Cuando cambias a una twig y haces un commit, entonces haz un git log --oneline --graph --decorate --all , ves algo como esto (del plugin Vim easymotion):

 * 4fb1af8 (origin/develop, develop) Update jumplist when moving cursor * fe9f404 Merge branch 'master' into develop |\ | * 667a668 (HEAD, tag: 1.3, origin/master, origin/HEAD, master) Merge pull request #34 from Layzie/master | |\ | | * 06826d7 fix EasyMotion#InitHL arguments | |/ | * afd0e42 Merge branch 'release/1.3' | |\ * | \ 44c6bfd Merge branch 'release/1.3' into develop |\ \ \ | | |/ | |/| | * | c4863f8 Update vim docs | * | 8dc93e6 Update README |/ / * | c1f1926 Update default leader key to <Leader><Leader> * | 6f0c9b9 Move most of the code to autoload/ 

Incluso sin el beneficio del color, es fácil ver lo que está pasando. La twig de desarrollo fue la más recientemente comprometida, por lo que se muestra en la parte superior. Si sigues la línea del lado izquierdo del gráfico, esos son los commit primarios de las twigs de develop y origin/develop . Todas las twigs 'fusionadas' entran por la derecha. La twig de develop tiene un compromiso de fusión donde se fusionó el master . Puede seguir el lado derecho de esa fusión a la twig maestra ( 667a668 ), que también es una combinación de fusión, que extrajo en Layzie/master ( 06826d7 ), que era claramente desarrollado en la parte superior de afd0e42 (que estaba claramente en la twig master (siga la línea hacia arriba para ver que la confirmación del primer padre del maestro lo incluye): todo el context necesario está en el gráfico). Esa combinación commit ( 667a668 ) te dice qué twig era: era Lazie / master, por lo que 06826d7 era la twig master del repository remoto de Layzie .

Aquí es donde sugeriría un hábito de flujo de trabajo: deje los posts de compromiso sobre lo que se combinó solo al fusionarse. Así es como puede (y debería, IMO) saber qué cometidos fueron en qué twigs (los jefes actuales son el mecanismo para decir qué commits están actualmente en qué twigs). La fusión dice "a mi izquierda está la twig de destino de la twig en la que me estoy fusionando. A la derecha está la twig en la que me estoy fusionando. En mi post de confirmación está el nombre al que se llamó la twig en la que me estoy fusionando. el momento en que lo fusioné "(importante punto implícito aquí: puede replace los nombres de las sucursales a voluntad mientras trabaja, y lo hago a menudo).

Al no hacer que los nombres de las twigs sean parte de los commits, puedes cherry-pick y rebase cosas sin ningún motivo para razonar acerca de la location cambiante de los commits, que es demasiado difícil y no útil. Un compromiso es solo una instantánea de tree completo, con algunos metadatos sobre quién lo creó, cuándo y dónde encaja en el dag de confirmaciones interconectadas. Esto le permite extraer compromisos de otras sucursales e incluso de repositorys de otras personas. He utilizado este poder para fusionar repos completamente diferentes, intercalando los compromisos juntos (lo contrario de lo que mencioné en mi primer ejemplo). Utilicé este poder para extraer el historial de un file particular de otro repository en una nueva twig, luego fusionarlo, para poder seguir su desarrollo en un lugar más sensato. Luego arrojé el repository original lleno de basura que ya no quería. Aquí puede ver algunos ejemplos de cómo son las confirmaciones de git líquido y cuánto puede hacer con ellas.

Si cherry-pick cuidadosamente una confirmación de la twig 'dev' de un compañero de trabajo, no me importa que sea sobre el coworker/dev de coworker/dev . Solo quiero ese trabajo en mi twig actual. Los metadatos de compromiso mostrarán que lo comprometí donde está ahora, y que mi compañero de trabajo fue el autor y cuando cada uno de nosotros hizo esas cosas. Ahora solo se trata de cambios en mi sucursal que no intentan descubrir que están en mi sucursal, pero solían estar en su sucursal. Sería un desastre intentar rastrear eso en un sistema tan flexible, y probablemente terminarías con información incorrecta con un sistema tratando de ser tan inteligente (tal vez no, pero parece un problema difícil). Digo que las fusiones te digan que quieres que se llamen las twigs, y deja que git clasifique las historias de los primeros padres a la izquierda para ti. Puedo decir que no he tenido problemas para seguir la historia, incluso para docenas de sucursales a la vez (y hemos tenido reposiciones terribles en el trabajo con tantas twigs paralelas que no caben en un monitor de pantalla ancha).