force - ''git pull origin mybranch'' deja mybranch local N compromete antes de origen. ¿Por qué?
git push (3)
¿Qué devuelve git remote -v show
cuando se trata de origen?
Si el origen apunta a github, el estado debe estar actualizado, y no adelantarse a ningún repositorio remoto. Al menos, con el Git1.6.5 lo estoy usando para una prueba rápida.
De todos modos, para evitar esto, defina explícitamente el repositorio remoto de la rama maestra:
$ git config branch.master.remote yourGitHubRepo.git
entonces un git pull origin master
, seguido de un git status
debería devolver un estado de limpieza (no adelante).
¿Por qué? porque el maestro de origen get fetch (incluido en el maestro de origen de git pull) no solo actualizaría FETCH_HEAD
(como explica Charles Bailey en su respuesta ), sino que también actualizaría la "rama principal remota" dentro de su repositorio local de Git.
En ese caso, su maestro local ya no parece estar "adelantado" al maestro remoto.
Puedo probar esto, con un git1.6.5:
Primero creo un workrepo:
PS D:/git/tests> cd pullahead
PS D:/git/tests/pullahead> git init workrepo
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/
PS D:/git/tests/pullahead> cd workrepo
PS D:/git/tests/pullahead/workrepo> echo firstContent > afile.txt
PS D:/git/tests/pullahead/workrepo> git add -A
PS D:/git/tests/pullahead/workrepo> git commit -m "first commit"
Simulo un repositorio de GitHub creando un repositorio desnudo (uno que puede recibir push desde cualquier lugar)
PS D:/git/tests/pullahead/workrepo> cd ..
PS D:/git/tests/pullahead> git clone --bare workrepo github
Agrego un modif a mi repositorio de trabajo, que presiono para github repo (agregado como un control remoto)
PS D:/git/tests/pullahead> cd workrepo
PS D:/git/tests/pullahead/workrepo> echo aModif >> afile.txt
PS D:/git/tests/pullahead/workrepo> git ci -a -m "a modif to send to github"
PS D:/git/tests/pullahead/workrepo> git remote add github d:/git/tests/pullahead/github
PS D:/git/tests/pullahead/workrepo> git push github
Creé un repositorio de inicio, clonado de GitHub, en el cual hago un par de modificaciones, presioné a GitHub:
PS D:/git/tests/pullahead/workrepo> cd ..
PS D:/git/tests/pullahead> git clone github homerepo
PS D:/git/tests/pullahead> cd homerepo
PS D:/git/tests/pullahead/homerepo> type afile.txt
firstContent
aModif
PS D:/git/tests/pullahead/homerepo> echo aHomeModif1 >> afile.txt
PS D:/git/tests/pullahead/homerepo> git ci -a -m "a first home modif"
PS D:/git/tests/pullahead/homerepo> echo aHomeModif2 >> afile.txt
PS D:/git/tests/pullahead/homerepo> git ci -a -m "a second home modif"
PS D:/git/tests/pullahead/homerepo> git push github
Luego clono workrepo para un primer experimento
PS D:/git/tests/pullahead/workrepo4> cd ..
PS D:/git/tests/pullahead> git clone workrepo workrepo2
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/
PS D:/git/tests/pullahead> cd workrepo2
PS D:/git/tests/pullahead/workrepo2> git remote add github d:/git/tests/pullahead/github
PS D:/git/tests/pullahead/workrepo2> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
* branch master -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
afile.txt | Bin 46 -> 98 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
En ese repositorio, el estado de git menciona el master geing antes del '' origin
'':
PS D:/git/tests/pullahead/workrepo5> git status
# On branch master
# Your branch is ahead of ''origin/master'' by 2 commits.
#
nothing to commit (working directory clean)
Pero eso es solo el origin
no es github:
PS D:/git/tests/pullahead/workrepo2> git remote -v show
github d:/git/tests/pullahead/github (fetch)
github d:/git/tests/pullahead/github (push)
origin D:/git/tests/pullahead/workrepo (fetch)
origin D:/git/tests/pullahead/workrepo (push)
Pero si repito la secuencia en un repositorio que tiene un origen en github (o no tiene ningún origen, solo se define un ''github'' remoto), el estado es limpio:
PS D:/git/tests/pullahead/workrepo2> cd ..
PS D:/git/tests/pullahead> git clone workrepo workrepo4
PS D:/git/tests/pullahead> cd workrepo4
PS D:/git/tests/pullahead/workrepo4> git remote rm origin
PS D:/git/tests/pullahead/workrepo4> git remote add github d:/git/tests/pullahead/github
PS D:/git/tests/pullahead/workrepo4> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
* branch master -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
afile.txt | Bin 46 -> 98 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
PS D:/git/tests/pullahead/workrepo4> git status
# On branch master
nothing to commit (working directory clean)
Si tuviera solo el origin
apuntando en github
, el status
estaría limpio para git1.6.5.
Puede ser con una advertencia de ''adelanto'' para git anterior, pero de todos modos, una git config branch.master.remote yourGitHubRepo.git
definida explícitamente debería ser capaz de encargarse de eso, incluso con versiones anteriores de Git.
Acabo de observar algo extraño sobre git pull
, que no entiendo.
El viernes, trabajé en una sucursal local. vamos a llamarlo mybranch
Antes de salir de la oficina lo empujé al origen (que es mi repositorio github): git push origin mybranch
.
Ayer en mi casa, saqué ed mybranch de mi computadora portátil, hice algo más de codificación y luego devolví mis cambios a github (origen).
Ahora vuelvo a trabajar y traté de llevar los cambios de ayer a mi máquina de trabajo (no cambié nada en el repositorio local de mi lugar de trabajo durante el fin de semana):
git pull origin mybranch
eso causó una fusión rápida hacia adelante, lo cual está bien. Luego hice un git status
, y dijo:
# On branch mybranch
# Your branch is ahead of ''origin/mybranch'' by 6 commits.
#
nothing to commit (working directory clean)
¿Huh? ¿Cómo pueden ser 6 compromisos futuros cuando ni siquiera lo toqué durante el fin de semana, Y simplemente saqué del origen? Así que ejecuté un git diff origin/mybranch
y los diffs fueron exactamente los 6 cambios que acabo de sacar del control remoto.
Solo pude "arreglarlo" ejecutando el git fetch origin
:
From [email protected]:me/project
af8be00..88b0738 mybranch -> origin/mybranch
Aparentemente, a mi repositorio local le faltaban algunos objetos de referencia, pero ¿cómo puede ser eso? Quiero decir, un tirón ya funciona, y no git fetch origin mybranch
en nada más que en esa rama, ¿así que un git fetch origin
git fetch origin mybranch
y git fetch origin mybranch
deberían tener el mismo resultado?
¿Debo usar siempre git pull origin
de git pull origin branchname
lugar de git pull origin branchname
?
Estoy confundido.
¿Tiene cuidado de agregar todo su control remoto (excepto el origin
que viene con su clon original) usando git remote add NAME URL
? He visto este error cuando se acaban de agregar a la configuración de git.
git pull
llama a git fetch
con los parámetros apropiados antes de fusionar los encabezados explícitamente obtenidos (o si ninguno la rama remota configurada para la fusión) en la rama actual.
La sintaxis: git fetch <repository> <ref>
donde <ref>
es solo un nombre de rama sin dos puntos es una captura ''one shot'' que no hace una búsqueda estándar de todas las ramas rastreadas del control remoto especificado, sino que busca solo la rama nombrada en FETCH_HEAD
.
Actualización: para las versiones de Git desde la versión 1.8.4, si hay una rama de seguimiento remoto que rastrea la referencia solicitada, la rama de rastreo ahora se actualizará mediante fetch
. Este cambio se ha realizado específicamente para evitar la confusión causada por el comportamiento anterior.
Cuando ejecuta git pull <repository> <ref>
, FETCH_HEAD
se actualiza como se FETCH_HEAD
anteriormente, luego se fusiona con su HEAD
desprotegido, pero no se actualizará ninguna de las ramas de seguimiento estándar para el repositorio remoto (Git <1.8.4). Esto significa que, a nivel local, parece que está por delante de la rama remota, mientras que, de hecho, está actualizado con ella.
Personalmente, siempre hago git fetch
seguido de git merge <remote>/<branch>
porque puedo ver cualquier advertencia sobre actualizaciones forzadas antes de fusionarme, y puedo obtener una vista previa de en qué me estoy fusionando. Si utilicé git pull
un poco más que yo, haría la mayoría de las veces un git pull
sin parámetros, confiando en branch.<branch>.remote
y branch.<branch>.merge
to '' branch.<branch>.merge
the right thing''.