Se compromete con la label y cómo se combina con la última versión del repository de Git

De acuerdo, no estoy tan familiarizado con Git. Me pidieron que clonara un repository del repository de alguien y luego usara la label. Entonces esto es lo que hice:

git clone someones_repo my_new_repo git checkout tags/bla_bla_tag -b tag_branch 

Así que ahora estoy en la versión de la label y no en la twig principal, sino en la label_ twig.

Hice cambios y quiero comprometerlos y fusionarlos con mi maestro y luego entregar mis cambios a nuestro repository oficial (creo que llaman a este repository de oro). Y aquí están mis preocupaciones:

  1. Esta twig "maestra", ¿contiene la última versión del repository que cloné? ¿O contiene la versión de la label?
  2. Si el maestro es la versión de la label y luego fusiono mis cambios, ¿qué sucederá si transfiero estos cambios combinados a nuestro repository oficial? ¿La versión más reciente del repository oficial se convertirá en la versión de mis cambios fusionados? Si alguien trata de clonar el repository oficial, ¿obtendrá él en su lugar mi versión fusionada ?.

Ya hay algunas buenas respuestas, pero lo que realmente podrías usar aquí es una ilustración gráfica.

La key para entender cómo funcionan las twigs y las tags en Git es darse count de que los nombres de las twigs y las tags son meros auxiliares. Hacen muy poco para hacer twigs. La misma palabra "twig" en sí misma es realmente ambigua en Git. Para ver más sobre esto y varios diagtwigs, click ¿Qué queremos decir con "twig"? Esto describe cómo las tags de twig seleccionan confirmaciones particulares, aunque no el process por el cual crece una twig. (Tenga en count también que la primera image del libro Pro Git está bien, pero al igual que Jubobs, no me gusta la segunda image Pro Git).

Utilizo un método de diagtwigción más simple en las publicaciones de StackOverflow. Tome este diagtwig de ejemplo de un repository con solo tres commits. Cada uno de estos tres commits tiene una identificación de hash real, una de esas cosas grandes y feas de 40 caracteres que se abrevia a badf00d y cafedad y demás, pero solo les doy nombres de una letra y pongo el nombre de la twig a la derecha:

 A <- B <- C <-- master 

Aquí C es nuestra última confirmación, en Branch master . El master nombre de twig contiene la identificación de hash real de la confirmación C , como ac0ffee4cafedad5badf00d... o lo que sea. Commit C sí mismo: la confirmación real, almacenada dentro de la database de Git, contiene el ID de la confirmación B Decimos que el master apunta a C , y C apunta a B B tiene la ID de A , por lo que apunta a A A fue el primer commit que alguna vez se haya hecho, por lo que no puede apuntar a ningún lado. No tiene padre , en los términos de Git; es un commit raíz .

Tenga en count que en este sistema, las confirmaciones de los padres no saben qué hijos tienen, pero los hijos conocen a sus padres. Para realizar una nueva confirmación en el master , Git escribe algunas cosas en la database y termina con el nuevo object de confirmación. El nuevo compromiso -llamémoslo D contiene el ID del compromiso actual como su padre, por lo que D apunta a C Luego, Git actualiza el nombre de la twig, master , para que apunte a D :

 A <- B <- C <- D 

(Como alguien señaló recientemente, esto es muy similar a search loggings de genealogía: encuentras algo como "Bob Jones, nacido de los padres Arthur y Sally". Obviamente, el logging de nacimiento de Bob no puede enumerar que 25 años después tendrá una hija , así que simplemente no. De manera similar, cuando haces un commit, Git sabe quién es el padre del commit, pero no tiene idea de si el commit tendrá hijos.

Con eso en mente, considere este fragment de gráfico. Dejé de dibujar las flechas internas para ahorrar espacio, pero recuerden que siempre apuntan hacia atrás (hacia la izquierda en estos dibujos):

 ...--D--E--F <-- master \ G--H <-- sidebr 

Llegamos aquí haciendo dos nuevos commits en master , es decir, E y F , pero también creando un nuevo nombre de twig, sidebr , apuntando a cometer D Luego git checkout sidebr y hacemos dos commits nuevos. Estos son G y H Cuando hacemos G , el compromiso D es actual, y es a lo que sidebr apunta. Así que Git escribe el compromiso con D como su padre y cambia sidebr para apuntar a G Ahora que G es actual, hacemos la nueva confirmación H con G como su padre, y actualizamos sidebr para que apunte a H , y así es como llegamos a este diagtwig.

Tiempo para las tags

Ahora es el momento de agregar tags a estas imágenes. Las tags son casi (pero no del todo) lo mismo que las twigs. Al igual que los nombres de las twigs, los nombres de las tags apuntan a commits. La diferencia key 1 es que se supone que los nombres de las twigs se mueven: crecen automáticamente al agregar nuevos commits. Los nombres de label no se deben mover.

Como resultado, también podríamos dibujarlos "dentro" del diagtwig de compromiso, en lugar de hacerlo a la derecha. (O, si tuviéramos color, podríamos usar diferentes colors para nombres de twigs y tags, pero no puedo hacer color en el text en StackOverflow.) Así que agreguemos un nombre de label que apunte a confirmar E :

  tag:v0.1 | v ...--D--E--F <-- master \ G--H <-- sidebr 

Esta label apunta a cometer E Debería siempre, para siempre, apuntar a E 2 Hay un hecho interesante sobre las ID de hash Git en bruto que es bastante relevante aquí: la ID de hash es totalmente determinista y se basa completamente en el contenido real de la confirmación (u otro object de Git). Por lo tanto, los nombres de label hacen poco más que proporcionar un nombre legible para humanos para una de esas espantosas identificaciones hash. Si todos pudiéramos recordar 17f9f635c101aef03874e1de1d8d0322187494b3 , no necesitaríamos la label v2.6.0 en el repository de Git para Git, pero ciertamente no voy a recordar eso. 3

En cualquier caso, puede git checkout cualquier confirmación por su ID, o por cualquier cosa que resuelva su ID. Un nombre de label funciona para este último y, por supuesto, es mucho más fácil de recordar. Entonces, dado el diagtwig de arriba, podemos verificar commit E con:

 git checkout v0.1 

(la tag: no es parte del nombre de la label, solo algo que escribí para decir por qué tenemos una flecha aquí). Esto, sin embargo, nos da un "HEAD separado", así que es por eso que git checkout -b newbranch v0.1 : que asigna un nuevo nombre de twig para apuntar a la confirmación. Ahora necesitamos volver a dibujar el gráfico un poco para darle más espacio:

  tag:v0.1 | | F <-- master v / ...--D--E <-- newbranch (HEAD) \ G--H <-- sidebr 

También agregué esta cosa HEAD : es un recordatorio de que ahora estamos en esta nueva twig. Si hacemos un nuevo commit ahora, esto hará crecer la twig de la manera habitual:

  tag:v0.1 | | F <-- master v / ...--D--E--I <-- newbranch (HEAD) \ G--H <-- sidebr 

La label, que no debe moverse, no se mueve. La twig , sin embargo, se mueve. Podemos hacer cualquier compromiso que nos guste, y cada uno hace que la newbranch actual, newbranch avance para incorporar cada uno de nuestros nuevos commits.


1 Otra diferencia importante es que los nombres de las tags viven en un espacio de nombre compartido, en todos los repositorys, mientras que las sucursales no. También hay tags anotadas , que le dan la oportunidad de adjuntar algunos datos no interpretados, y Git le permite firmar dichas tags mediante el encryption GPG. Pero eso es para otra discusión.

2 Es posible mover una label a la fuerza, o eliminarla y volver a crearla apuntando a una confirmación diferente. A veces incluso hay una buena razón para hacer eso. Solo necesita asegurarse de que la razón sea especialmente buena, ya que la label es solo un nombre legible para humanos para la ID de hash, y cualquier repository que ya tenga la label anterior, es probable que piense que la antigua label-a-hash- La asignación de ID sigue siendo correcta, incluso después de mover la label a la fuerza.

3 Utilicé git rev-parse v2.6.0 para encontrarlo. La ID de hash anterior es la ID del object de label anotado (que puedes encontrar clonando el repository de Git para Git). La confirmación real es be08dee9738eaaa0423885ed189c2b6ad8368cf0 . Hay una syntax especial para encontrar el ID de compromiso en un solo paso, usando git rev-parse , o puede usar git show v2.6.0 para leer el object de label, y luego git show el object de destino de la label para ver el compromiso, por ejemplo.

Cuando crea una ramificación de una "label", crea un puntero a una confirmación. La label apunta a una confirmación y tu twig es como un puntero a esta confirmación también. Si este commit está en la twig master o no, es imposible decirlo sin más información.

Para get el último maestro puedes hacer git fetch y el último master estará en origin/master .

Por ejemplo, si ha creado una confirmación basada en la confirmación labelda, puede entregarla de la siguiente manera:

 git checkout master git pull -r git cherry-pick <your commit> git push origin master 

En lenguaje sencillo esto significaría. Checkout maestro local. Actualice el maestro local para que coincida con el maestro remoto. Coloque su nueva confirmación ontop del maestro local y actualice el maestro local para señalar este compromiso. Entregar maestro local a maestro remoto.

No estoy seguro de a qué se refería con "entregar los cambios en el repository principal". Espero que sea una request de extracción y no un impulso directamente al repository de oro

  1. El maestro de tu sucursal local será el mismo que el de ese depósito de esa persona. Puede ser el mismo que el maestro del repo de oro, si esos dos repos se mantienen regularmente sincronizados.

  2. Una label es solo una label que agrega a alguna confirmación, generalmente para una confirmación en el maestro. Si su request de extracción se fusiona, el maestro en golden repo se convertirá en su versión de master. Y si alguien clona el repository de oro obtendrá su versión de request.

Yo recomendaría usar el flujo de trabajo de request de extracción para esto. De lo contrario, la posibilidad de perder compromisos es muy alta

Para sus preguntas:

  1. Para el repository que clonó, solo puede estar seguro de que la hora de clonación es la versión más reciente. Si su colega realiza algunos cambios para su repository después de que lo haya clonado, entonces su repository local no es la última versión. Y el repository clonado contiene tags que existen en el repository de su colega. Hay una forma de verificar si su repository local es la última versión:

git fetch origin git log master..origin/master

Si tiene salida, eso significa que su maestro local no es la última versión, debe usar git pull para get cambios.

  1. Si la label que utiliza está en la twig principal y fusiona los cambios en el maestro, la última versión para el repository oficial se convertirá en la nueva versión que fusionó. Y después de eso, si no clonamos el repo oficial, la última versión de la twig maestra también es la versión que fusionaste.

PD: Si tanto usted como su colega trabajan para el repository oficial, debe clonar desde el repository oficial al principio.