Creo que su problema básico aquí es que está malinterpretando y / o malinterpretando lo que hace git y por qué lo hace.
Cuando clonas algún otro repositorio, git hace una copia de lo que sea que esté "allí". También toma "sus" etiquetas de rama, como master
, y hace una copia de esa etiqueta cuyo "nombre completo" en su árbol git es (normalmente) remotes/origin/master
(pero en su caso, remotes/upstream/master
). La mayoría de las veces también puede omitir la remotes/
parte, por lo que puede referirse a esa copia original como upstream/master
.
Si ahora realiza y confirma algunos cambios en algunos archivos, es el único que tiene esos cambios. Mientras tanto, otras personas pueden usar el repositorio original (desde el cual hizo su clon) para hacer otros clones y cambiar esos clones. Son los únicos con sus cambios, por supuesto. Sin embargo, eventualmente, alguien puede tener cambios que enviar al propietario original (a través de "push" o parches o lo que sea).
El git pull
comando es principalmente una abreviatura de git fetch
seguido de git merge
. Esto es importante porque significa que debe comprender qué hacen realmente esas dos operaciones.
El git fetch
comando dice que regrese a donde haya clonado (o que haya configurado como un lugar para buscar) y busque "cosas nuevas que alguien más agregó, modificó o eliminó". Esos cambios se copian y se aplican a su copia de lo que obtuvo anteriormente . Están no aplicar a su propio trabajo, sólo para ellos.
El git merge
comando es más complicado y es donde te va mal. Lo que hace, simplificado un poco, es comparar "lo que cambió en su copia" con "los cambios que obtuvo de otra persona y, por lo tanto, se agregaron a su-copia-del-trabajo-de-otra-persona". Si sus cambios y sus cambios no parecen entrar en conflicto, la merge
operación los mezcla y le da un "compromiso de fusión" que une su desarrollo y su desarrollo (aunque hay un caso "fácil" muy común en el que no tiene cambios y obtienes un "avance rápido").
La situación se está encontrando ahora es uno en el que se han realizado cambios y los nueve cometido veces, de hecho, de ahí el "9 por delante", y que han hecho que no hay cambios. Entonces, fetch
obedientemente no busca nada, y luego merge
toma su falta de cambios y tampoco hace nada.
Lo que quiere es mirar, o tal vez incluso "restablecer", "su" versión del código.
Si simplemente desea verlo, simplemente puede verificar esa versión:
git checkout upstream/master
Eso le dice a git que desea mover el directorio actual a la rama cuyo nombre completo es en realidad remotes/upstream/master
. Verá su código desde la última vez que ejecutó git fetch
y obtuvo su código más reciente.
Si desea abandonar todos sus propios cambios, lo que debe hacer es cambiar la idea de git de qué revisión master
debe nombrar su etiqueta . Actualmente nombra su confirmación más reciente. Si vuelve a esa rama:
git checkout master
entonces el git reset
comando le permitirá "mover la etiqueta", por así decirlo. El único problema que queda (suponiendo que esté realmente listo para abandonar todo lo que ha hecho) es encontrar dónde debe apuntar la etiqueta.
git log
le permitirá encontrar los nombres numéricos, esas cosas como, 7cfcb29
que son nombres permanentes (que nunca cambian), y hay una cantidad ridícula de otras formas de nombrarlos, pero en este caso solo desea el nombre upstream/master
.
Para mover la etiqueta, acabando con sus propios cambios (cualquiera que haya cometido en realidad son recuperables durante bastante tiempo, pero es mucho más difícil después de este modo ser muy seguro):
git reset --hard upstream/master
Le --hard
dice a git que borre lo que ha estado haciendo, mueva la etiqueta de rama actual y luego verifique la confirmación dada.
No es muy común que realmente quieren git reset --hard
y acabar con un montón de trabajo. Un método más seguro (lo que hace que sea mucho más fácil recuperar ese trabajo si, después de todo, decide que algo valió la pena) es cambiar el nombre de su rama existente:
git branch -m master bunchofhacks
y luego hacer una nueva rama local llamada master
que "rastrea" (realmente no me gusta este término porque creo que confunde a la gente, pero ese es el término git :-)) el maestro de origen (o aguas arriba):
git branch -t master upstream/master
con el que luego puedes seguir adelante:
git checkout master
Lo que hacen los últimos tres comandos (hay atajos para que sean solo dos comandos) es cambiar el nombre pegado en la etiqueta existente, luego crear una nueva etiqueta y luego cambiar a ella:
antes de hacer nada:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "master"
despues git branch -m
:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
despues git branch -t master upstream/master
:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
Aquí C0
está la última confirmación (un árbol de fuentes completo) que obtuvo la primera vez que hizo su git clone
. C1 a C9 son sus confirmaciones.
Tenga en cuenta que si lo hiciera git checkout bunchofhacks
y luego git reset --hard HEAD^^
, esto cambiaría la última imagen a:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks"
\
\- C8 --- C9
La razón es que HEAD^^
nombra la revisión dos hacia arriba desde el encabezado de la rama actual (que sería justo antes del reinicio bunchofhacks
), y reset --hard
luego mueve la etiqueta. Las confirmaciones C8 y C9 ahora son en su mayoría invisibles (puede usar cosas como el reflog y git fsck
encontrarlas, pero ya no es trivial). Tus etiquetas son tuyas para moverlas como quieras. El fetch
comando se encarga de los que empiezan remotes/
. Es convencional hacer coincidir "tuyo" con "de ellos" (así que si tienen un remotes/origin/mauve
nombre tuyo mauve
también), pero puedes escribir "de ellos" cuando quieras nombrar / ver las confirmaciones que obtuviste "de ellos". (Recuerde que "una confirmación" es un árbol de fuentes completo. Puede seleccionar un archivo específico de una confirmación, git show
por ejemplo,