Saltar al contenido

¿Qué hace exactamente git fetch?

Ya no necesitas investigar más en otros sitios porque llegaste al lugar exacto, contamos con la respuesta que buscas sin complicaciones.

Solución:

git fetch en sí mismo es bastante simple. Las partes complicadas vienen antes y después.

Lo primero que debe saber aquí es que Git almacena comete. De hecho, esto es esencialmente de lo que se trata Git: administra una colección de confirmaciones. Esta colección rara vez encoge: en su mayor parte, lo único que haces con esta colección de confirmaciones es agregar nuevas confirmaciones.

Confirmaciones, el índice y el árbol de trabajo

Cada confirmación tiene varios datos, como el nombre del autor y la dirección de correo electrónico y una marca de tiempo. Cada confirmación también guarda una instantánea completa de todos los archivos que le indicó: estos son los archivos almacenados en su índice (también conocido como tu área de ensayo) en el momento en que corriste git commit. Esto también es cierto para las confirmaciones que obtiene de otra persona: guardan los archivos que estaban en el índice del otro usuario en el momento en que el otro usuario ejecutó git commit.

Tenga en cuenta que cada repositorio de Git tiene solo un índice, al menos inicialmente. Este índice está vinculado con el árbol de trabajo. En las versiones más recientes de Git, puede usar git worktree add para agregar árboles de trabajo adicionales; cada nuevo árbol de trabajo viene con un nuevo índice / área de preparación. El objetivo de este índice es actuar como un contenedor de archivos intermedio, situado entre “la confirmación actual” (también conocida como HEAD) y el árbol de trabajo. Inicialmente, el HEAD commit y el índice normalmente coinciden: contienen las mismas versiones de todos los archivos confirmados. Git copia los archivos de HEAD en el índice, y luego del índice en el árbol de trabajo.

Es fácil ver el árbol de trabajo: tiene sus archivos en su formato normal, donde puede verlos y editarlos con todas las herramientas habituales de su computadora. Si escribe código Java o Python, o HTML para un servidor web, el compilador, el intérprete o el servidor web pueden utilizar los archivos del árbol de trabajo. Los archivos almacenados en el índice y almacenados en cada confirmación de Git, hacen no tienen esta forma y son no utilizable por los compiladores, intérpretes, servidores web, etc.

Otra cosa para recordar acerca de las confirmaciones es que una vez que un archivo está en una confirmación, no puede ser cambiado. Ninguna parte de cualquier compromiso puede cambiar. Por lo tanto, una confirmación es permanente, o al menos, permanente a menos que se elimine (lo que se puede hacer, pero es difícil y generalmente indeseable). Sin embargo, lo que está en el índice y en el árbol de trabajo se puede modificar en cualquier momento. Por eso existen: el índice es casi una “confirmación modificable” (excepto que no se guarda hasta que ejecuta git commit), y el árbol de trabajo mantiene los archivos en la forma que el resto de la computadora puede usar.1


1No es necesario tener ambos El índice y el árbol de trabajo. El VCS podría tratar el árbol de trabajo como el “compromiso modificable”. Esto es lo que hace Mercurial; es por eso que Mercurial no necesita un índice. Podría decirse que este es un diseño mejor, pero no es la forma en que funciona Git, por lo que cuando usa Git, tiene un índice. La presencia del índice es una gran parte de lo que hace que Git sea tan rápido: sin él, Mercurial tiene que ser muy inteligente y aún no es tan rápido como Git.


Se compromete a recordar a sus padres; las nuevas confirmaciones son hijos

Cuando haces un nuevo comprometerse corriendo git commit, Git toma el contenido del índice y crea una instantánea permanente de todo lo que contiene en ese momento. (Es por eso que debes git add archivos: los copia de su árbol de trabajo, donde los ha cambiado, de nuevo a su índice, de modo que estén listos para ser “fotografiados” para la nueva instantánea.) Git también recopila un mensaje de confirmación y, por supuesto, usa su nombre y dirección de correo electrónico y la hora actual, para realizar la nueva confirmación.

Pero Git también almacena, en la nueva confirmación, el ID de hash del compromiso actual. Decimos que el nuevo compromiso “apunta hacia atrás” al compromiso actual. Considere, por ejemplo, este simple repositorio de tres confirmaciones:

A <-B <-C   <-- master (HEAD)

Aquí decimos que el nombre de la sucursalmaster "apunta a" la tercera confirmación, que he etiquetado C, en lugar de usar uno de los ID de hash incomprensibles de Git como b06d364.... (El nombre HEAD se refiere al nombre de la sucursal, master. Así es como Git puede girar la cuerda HEAD en el ID de hash correcto: Git sigue HEAD para master, luego lee el ID de hash de master.) Es compromiso C en sí mismo que "apunta a" - retiene el ID de hash de - commit B, aunque; y comprometerse B puntos para comprometer A. (Desde cometer A es la primera confirmación de la historia, no hay una confirmación anterior a la que apunte, por lo que no apunta a ninguna parte, lo que la hace un poco especial. A esto se le llama compromiso de root.)

Hacer un nuevo commit, Git empaqueta el índice en una instantánea, lo guarda con su nombre y dirección de correo electrónico, etc. y incluye el ID de hash de la confirmación C, para realizar una nueva confirmación con un nuevo ID de hash. Usaremos D en lugar del nuevo ID de hash, ya que no sabemos cuál será el nuevo ID de hash:

A <-B <-C <-D

Note como D puntos a C. Ahora eso D existe, Git altera el ID de hash almacenado bajo el nombre master, para almacenar DID de hash en lugar de C's. El nombre almacenado en HEAD en sí mismo no cambia en absoluto: sigue siendo master. Entonces ahora tenemos esto:

A <-B <-C <-D   <-- master (HEAD)

Puede ver en este diagrama cómo funciona Git: dado un nombre, como master, Git simplemente sigue la flecha para encontrar el más reciente cometer. Esa confirmación tiene una flecha hacia atrás a su anterior o padre commit, que tiene otra flecha hacia atrás a su propio padre, y así sucesivamente, a lo largo de todos sus ancestros que conducen de regreso a la confirmación raíz.

Tenga en cuenta que mientras los niños recuerdan a sus padres, el padre se compromete a no recordar a sus hijos. Esto es porque ninguna parte de cualquier compromiso puede cambiar nunca: Git literalmente hipocresía agregue los hijos al padre, y ni siquiera lo intenta. Git siempre debe funcionar al revés, de más nuevo a más antiguo. Todas las flechas de confirmación apuntan automáticamente hacia atrás, por lo que normalmente ni siquiera las dibujo:

A--B--C--D   <-- master (HEAD)

Repositorios distribuidos: que git fetch lo hace

Cuando usamos git fetch, tenemos dos Gits diferentes, con diferentes, pero relacionado—Depositorios. Supongamos que tenemos dos repositorios de Git, en dos computadoras diferentes, que ambos comienzan con esas mismas tres confirmaciones:

A--B--C

Debido a que comienzan con las mismas confirmaciones exactas, estas tres confirmaciones también tienen los mismos ID de hash. Esta parte es muy inteligente y es la razón por la que las ID de hash son como son: la ID de hash es una suma de comprobación2 de El contenido de la confirmación, de modo que dos confirmaciones que sean exactamente idénticas siempre tengan la mismo ID de hash.

Ahora, usted, en su Git y su repositorio, han agregado una nueva confirmación D. Mientras tanto, ellos, quienesquiera que sean, pueden haber agregado sus propias nuevas confirmaciones. Usaremos letras diferentes ya que sus confirmaciones necesariamente tendrán diferentes valores hash. También veremos esto principalmente desde su punto de vista (de Harry); los llamaremos "Sally". Agregaremos una cosa más a nuestra imagen de tu repositorio: ahora se ve así:

A--B--C   <-- sally/master
       
        D   <-- master (HEAD)

Ahora supongamos que Sally hizo dos confirmaciones. En ella repositorio, ella ahora tiene esto:

A--B--C--E--F   <-- master (HEAD)

o tal vez (si te busca, pero aún no ha corrido git fetch):

A--B--C   <-- harry/master
       
        E--F   <-- master (HEAD)

Cuando usted correr git fetch, conectas tu Git con el Git de Sally y le preguntas si tiene nuevas confirmaciones agregadas a ellamaster desde cometer C. Ella lo hace, tiene sus nuevos compromisos E y F. Entonces, su Git obtiene esas confirmaciones de ella, junto con todo lo necesario para completar las instantáneas de esas confirmaciones. Tu Git luego agrega esos compromisos a tu repositorio, para que ahora tenga esto:

        E--F   <-- sally/master
       /
A--B--C
       
        D   <-- master (HEAD)

Como puede ver, ¿qué git fetch que hiciste por ti fue recogerla toda nuevo se compromete y agrégalos a tu repositorio.

Para recordar donde ellamaster es decir, ahora que ha hablado con su Git, sus copias de Git ella maestro a tusally/master. Tu propio mastery el tuyo HEAD, no cambies en absoluto. Solo estos nombres de "memoria de otro repositorio de Git", que Git llama nombres de sucursales de seguimiento remoto, cambio.


2Este hash es un hash criptográfico, en parte para que sea difícil engañar a Git, y en parte porque los hash criptográficos se comportan naturalmente bien para los propósitos de Git. El hash actual usa SHA-1, que era seguro, pero ha sufrido ataques de fuerza bruta y ahora está siendo abandonado por la criptografía. Es probable que Git se mueva a SHA2-256 o SHA3-256 o algún otro hash más grande. Habrá un período de transición con algunas molestias. 🙂


Ahora debería fusionar o volver a establecer una base:git reset es generalmente incorrecto

Tenga en cuenta que, una vez que haya obtenido de Sally, es tu repositorio, y solamente su repositorio, que tiene todo el trabajo de ambos. Sally todavía no tiene tu nuevo compromiso D.

Esto sigue siendo cierto incluso si en lugar de "Sally", tu otro Git se llama origin. Ahora que tienes ambos master y origin/master, debes hacer algo para conectar tu nueva confirmación D con su último compromiso F:

A--B--C--D   <-- master (HEAD)
       
        E--F   <-- origin/master

(Me mudé D en la parte superior por motivos de dibujo de gráficos, pero este es el mismo gráfico que antes,

Sus dos opciones principales aquí son usar git merge o git rebase. (Hay otras formas de hacer esto, pero estas son las dos para aprender).

Fusionar es más simple ya que git rebase hace algo que involucra la forma verbal de fusionar, fusionar. Qué git merge hace es ejecutar la forma verbal de fusionar, y luego confirmar el resultado como un nuevo compromiso que se llama fusionar compromiso o simplemente "una fusión", que es la forma sustantiva de fusión. Podemos dibujar el nuevo compromiso de fusión G Por aquí:

A--B--C--D---G   <-- master (HEAD)
           /
        E--F   <-- origin/master

A diferencia de un compromiso regular, un fusionar compromiso tiene dos padres.3 Se conecta de nuevo a las dos confirmaciones anteriores que se usaron para realizar la fusión. Esto hace posible impulsar su nuevo compromiso G para origin: G lleva consigo tu D, pero también se conecta a su F, por lo que su Git está bien con esta nueva actualización.

Esta fusión es el mismo tipo de fusión que se obtiene al fusionar dos ramas. Y de hecho, tu hizo fusiona dos ramas aquí: fusionaste tu master con Sally (o origin's) master.

Utilizando git rebase suele ser fácil, pero lo que hace es más complicado. En lugar de fusionando tu compromiso D con su compromiso F para hacer una nueva fusionar compromisoG, qué git rebase lo que hace es Copiar cada uno de tus compromisos para que el nuevo copias, que son confirmaciones nuevas y diferentes, vienen después de la última confirmación en tu río arriba.

Aquí, tu corriente arriba es origin/master, y los compromisos que tienes que no son solo tu compromiso D. Entonces git rebase hace un Copiar de D, que voy a llamar D', colocando la copia después de su confirmación F, así que eso D'el padre es F. El gráfico intermedio se ve así:5

A--B--C--D   <-- master
       
        E--F   <-- origin/master
            
             D'   <-- HEAD

El proceso de copia usa el mismo código de fusión que git merge usa para hacer la forma verbal, fusionar, de tus cambios desde el compromiso D.4 Sin embargo, una vez que se realiza la copia, el código de rebase ve que no hay más confirmaciones para copiar, por lo que cambios tu master rama para apuntar a la confirmación copiada final D':

A--B--C--D   [abandoned]
       
        E--F   <-- origin/master
            
             D'   <-- master (HEAD)

Esto abandona el compromiso original D.6 Esto significa que también podemos dejar de dibujarlo, así que ahora obtenemos:

A--B--C--E--F   <-- origin/master
             
              D'   <-- master (HEAD)

Ahora es fácil git push tu nuevo compromiso D' de regreso origin.


3En Git (pero no en Mercurial), una confirmación de fusión puede tener más de dos padres. Esto no hace nada que no puedas hacer mediante la combinación repetida, por lo que es principalmente para presumir. 🙂

4Técnicamente, el compromiso base de fusión, al menos para este caso, es compromiso C y las dos confirmaciones de propinas son D y F, entonces en este caso es literalmente exactamente lo mismo. Si reajusta más de una confirmación, se vuelve un poco más complicado, pero en principio sigue siendo sencillo.

5Este estado intermedio, donde HEAD está separado de master, suele ser invisible. Solo lo ve si algo sale mal durante la forma verbal de fusión, por lo que Git se detiene y tiene que pedirle ayuda para finalizar la operación de fusión. Cuando eso lo hace Sin embargo, cuando hay un conflicto de fusión durante el rebase, es importante saber que Git se encuentra en este estado de "CABEZA separada", pero siempre que el rebase se complete por sí solo, no tienes que preocuparte tanto por esto. .

6La cadena de confirmación original se retiene temporalmente a través de Git reflogs y a través del nombre ORIG_HEAD. los ORIG_HEAD El valor se sobrescribe con la siguiente operación que realiza un "gran cambio", y la entrada reflog eventualmente caduca, normalmente después de 30 días para esta entrada. Después de eso, un git gc realmente eliminará la cadena de confirmación original.


los git pull el comando simplemente se ejecuta git fetch y luego un segundo comando

Tenga en cuenta que después git fetch, normalmente tienes que ejecutar un segundo comando de Git, ya sea git merge o git rebase.

Si sabe de antemano que, con certeza, utilizará inmediatamente uno de esos dos comandos, puede utilizar git pull, la cual recorre git fetch y luego ejecuta uno de esos dos comandos. Tu eliges cual segundo comando para ejecutar mediante la configuración pull.rebase o abasteciendo --rebase como una opción de línea de comandos.

Hasta que esté bastante familiarizado con cómo git merge y git rebase trabajo, sin embargo, sugiero no utilizando git pull, porque a veces git merge y git rebase no se completan por sí mismos. En este caso, usted debe saber cómo lidiar con este fracaso. usted debe saber qué comando ejecutó realmente. Si ejecuta el comando usted mismo, sabrá qué comando ejecutó y dónde buscar ayuda si es necesario. Si tu corres git pull, ¡es posible que ni siquiera sepa qué segundo comando ejecutó!

Además de esto, a veces es posible que desee Mira antes de ejecutar el segundo comando. Cuantas confirmaciones hicieron git fetch ¿traer? ¿Cuánto trabajo será hacer una fusión frente a una rebase? ¿Es mejor fusionar que rebase en este momento, o es mejor rebase que fusionar? Contestar alguna de estas preguntas, debe separar el git fetch paso desde el segundo comando. Si utiliza git pull, usted debe Decida de antemano qué comando ejecutar, incluso antes de saber cuál es el que debe usar.

En resumen, solo use git pull después de que se familiarice con la forma en que las dos partes:git fetchy el segundo comando que elija, realmente funciona.

No tienes que hacer dos confirmaciones separadas y git fetch no dejará caer ningún registro.

 --o--o--o (origin/master)
          
           x--x (master: my local commits)

Lo que debe hacer es reajustar su confirmación local sobre cualquier nueva confirmación obtenida por el git fetch mando:

git fetch

--o--o--o--O--O (origin/master updated)
         
          x--x (master)

git rebase origin/master

--o--o--o--O--O (origin/master updated)
               
                x'--x' (master rebased)

git push

--o--o--o--O--O--x'--x' (origin/master, master)

Aún más simple, desde Git 2.6, usaría la configuración:

git config pull.rebase true
git config rebase.autoStash true

Entonces un simple git pull reproduciría automáticamente sus confirmaciones locales además de origin/master. Entonces tú puedes git push.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *