Restablezca la rama del repositorio local para que sea como el repositorio remoto HEAD

3858

¿Cómo restablezco mi rama local para que sea igual que la rama en el repositorio remoto?

Yo hice:

git reset --hard HEAD

Pero cuando corro un git status,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   java/com/mycompany/TestContacts.java
      modified:   java/com/mycompany/TestParser.java

¿Puede decirme por qué tengo estos 'modificados'? No he tocado estos archivos? Si lo hice, quiero eliminarlos.

hap497
fuente
8
De acuerdo con la salida de git statussu segundo comando git reset --hard HEADfalló. Sin embargo, no pegaste su salida. → Pregunta incompleta.
Robert Siemer
2
Aquí está mezclando dos problemas: 1) cómo restablecer una rama local al punto donde está el control remoto y 2) cómo borrar su área de preparación (y posiblemente el directorio de trabajo), eso git statusdice nothing to commit, working directory clean. - ¡Por favor especifica!
Robert Siemer

Respuestas:

6700

La configuración de su rama para que coincida exactamente con la rama remota se puede hacer en dos pasos:

git fetch origin
git reset --hard origin/master

Si desea guardar el estado actual de su sucursal antes de hacerlo (por si acaso), puede hacer lo siguiente:

git commit -a -m "Saving my work, just in case"
git branch my-saved-work

Ahora su trabajo se guarda en la rama "mi-trabajo-guardado" en caso de que decida que desea recuperarlo (o si desea verlo más tarde o compararlo con su rama actualizada).

Tenga en cuenta que el primer ejemplo supone que el nombre del repositorio remoto es "origen" y que la rama llamada "maestro" en el repositorio remoto coincide con la rama actualmente desprotegida en su repositorio local.

Por cierto, esta situación en la que se encuentra se parece mucho a un caso común en el que se ha realizado un empuje en la rama actualmente desprotegida de un repositorio no descubierto. ¿Ingresaste recientemente a tu repositorio local? De lo contrario, no se preocupe, algo más debe haber causado que estos archivos terminen modificados inesperadamente. De lo contrario, debe tener en cuenta que no se recomienda ingresar a un repositorio no desnudo (y no a la rama actualmente desprotegida, en particular).

Dan Molding
fuente
44
Gracias por su respuesta. Usted dijo 'Tenga en cuenta que el primer ejemplo asume que el nombre del repositorio remoto es "origen" y que la rama llamada "maestro" en el repositorio remoto coincide con la sucursal en su repositorio local. ¿Cómo puedo verificar el nombre de mi repositorio remoto y el nombre de mi sucursal antes de ejecutar 'git reset --hard'? Gracias de nuevo.
hap497
21
Si no nombró explícitamente el control remoto, es probable que su nombre sea solo "origen" (el valor predeterminado). Puede usar "git remote" para obtener una lista de todos los nombres remotos. Luego puede usar "git remote <name>" para ver qué ramas se empujan / tiran entre sí (por ejemplo, si su rama "master" se clonó de "master" en el control remoto llamado "origin", obtendrá una línea que dice "maestro se fusiona con maestro remoto").
Dan Molding
66
"no se recomienda ingresar a un repositorio no desnudo (y no a la rama actualmente desprotegida, en particular" ¿Por qué?
LeeGee
27
Justo después de ir a buscar, creo que también puedes hacerlo git reset FETCH_HEAD --hard, ese es el mismo significado.
Jean
66
No eliminó los archivos que he agregado.
Trismegistos
417

Tenía que hacer (la solución en la respuesta aceptada):

git fetch origin
git reset --hard origin/master

Seguido por:

git clean -f

para eliminar archivos locales

Para ver qué archivos se eliminarán (sin eliminarlos realmente):

git clean -n -f
Akavall
fuente
89
también, git clean -d -fsi hay directorios no rastreados presentes.
Garg
54
tambiéngit clean -fdx
Swapnil Kotwal
14
Si desea una copia exacta de la rama remota, debe seguir git clean -ffdx. Tenga en cuenta que hay dos f.
Trismegistos
66
El git clean -fera la pieza esencial que necesitaba. ¡Gracias!
dgo
17
tenga cuidado al usar el comando clean. Puede eliminar archivos ignorados de otras ramas.
mikoop
307

Primero, reinicie a la búsqueda anterior HEADde la rama ascendente correspondiente:

git reset --hard @{u}

La ventaja de especificar @{u}o su forma detallada @{upstream}es que el nombre del repositorio remoto y la rama no tienen que especificarse explícitamente.

A continuación, según sea necesario, elimine los archivos no rastreados, opcionalmente también con -x:

git clean -df

Finalmente, según sea necesario, obtenga los últimos cambios:

git pull
Acumenus
fuente
54
Esta parece una mejor respuesta que la aceptada, ya que se restablece dinámicamente a la rama ascendente actual en lugar de siempre una estática como, por ejemploorigin/master
Jon z
@Jonz, el @{upstream}es muy útil y se puede usar en alias:alias resetthisbranch="git reset --hard @{upstream}"
Siddhartha
1
@GangadharJannu git reset --hardrequiere una confirmación, de lo contrario no sabría a qué reiniciarlo. @{u}apunta a una confirmación específica: el jefe de la rama rastreada, desde la última vez que hizo una git fetch.
Kristoffer Bakkejord
1
@KristofferBakkejord Gracias por la explicación, pero incluso sin comprometer hash podemos hacerlo, git reset --hardaunque no se restablecerá a la sucursal remota
Gangadhar JANNU
3
Para cualquier otra persona que casi abre una nueva pregunta aquí, si obtiene de Powershell, utilice comillas ( git reset --hard "@{u}"). Me tomó un tiempo entenderlo.
MPStoering
112

git reset --hard HEADen realidad solo se restablece al último estado comprometido. En este caso, HEAD se refiere a la HEAD de su rama.

Si tiene varias confirmaciones, esto no funcionará.

Lo que probablemente quiera hacer es restablecer la cabecera de origen o como se llame su repositorio remoto. Probablemente solo haría algo como

git reset --hard origin/HEAD

Pero ten cuidado. Los reinicios duros no se pueden deshacer fácilmente. Es mejor hacer lo que Dan sugiere, y ramificar una copia de sus cambios antes de reiniciar.

Mikael Ohlson
fuente
2
Hubo una sugerencia incorrecta en mi respuesta que Dan captó antes. Lo edité, ya que no quiero engañar a nadie. En cuanto al origen / maestro o origen / HEAD, espero que eso dependa de si realmente realizas una búsqueda primero o no. Si acaba de clonar el origen, y no tenía otras ramas, lo que me parece bastante común, entonces debería restablecerlo bien. Pero, por supuesto, Dan tiene razón.
Mikael Ohlson
73

Todas las sugerencias anteriores son correctas, pero a menudo para realmente restablecer su proyecto, también necesita eliminar incluso los archivos que están en su .gitignore.

Para obtener el equivalente moral de borrar el directorio de su proyecto y volver a clonar desde el control remoto es:

git fetch
git reset --hard
git clean -x -d -f

Advertencia : git clean -x -d -fes irreversible y puede perder archivos y datos (por ejemplo, cosas que ha ignorado usar .gitignore).

Christopher Smith
fuente
12
Advertencia: "git clean -x -d -f" es irreversible y puede perder archivos y datos en .gitignore
Akarsh Satija
Un poco más corto: git clean -xdfeso es igual a git clean -x -d -f.
Kiryl
git clean -ffxd para eliminar todo lo que no está en el repositorio
Trismegistos
44

Usa los comandos a continuación. Estos comandos también eliminarán todos los archivos no rastreados de git local

git fetch origin
git reset --hard origin/master
git clean -d -f
Jamsheer
fuente
66
Esta es una respuesta más completa porque sin el git clean -d -ftodavía tendremos algunas cosas de la antigua rama en el directorio local. Gracias hombre.
Flavio
3
Esto es lo que REALMENTE hace que sea como el control remoto. La limpieza es importante.
David S.
1
git clean -ffxd para eliminar todo verdaderamente
Trismegistos
1
Esto es exactamente lo que necesitaba. Gracias
AllJs
38

La pregunta mezcla dos cuestiones aquí:

  1. cómo restablecer una rama local al punto donde está el control remoto
  2. cómo borrar su área de preparación (y posiblemente el directorio de trabajo), por lo que git statusdicenothing to commit, working directory clean.

La respuesta única es:

  1. git fetch --prune (opcional) Actualiza la instantánea local del repositorio remoto. Otros comandos son solo locales.
    git reset --hard @{upstream}Coloca el puntero de la rama local en el lugar donde se encuentra la instantánea del control remoto, y establece el índice y el directorio de trabajo en los archivos de esa confirmación.
  2. git clean -d --force Elimina archivos y directorios no rastreados que dificultan que git diga "limpieza de directorio de trabajo".
Robert Siemer
fuente
1
La @{upstream}sintaxis requiere que se configure en sentido ascendente, lo que ocurre de manera predeterminada si usted git checkout <branchname>. - De lo contrario, reemplácelo con origin/<branchname>.
Robert Siemer
Agregue -xa git cleanpara eliminar todo lo que no esté en la confirmación (es decir, incluso los archivos ignorados con el mecanismo .gitignore).
Robert Siemer
22

Esto es algo a lo que me enfrento regularmente, y he generalizado el script que Wolfgang proporcionó anteriormente para trabajar con cualquier rama

También agregué un mensaje "¿estás seguro?" Y algunos resultados

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# AT 2012-11-09
# see http://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
branchname=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
read -p "Reset branch $branchname to origin (y/n)? "
[ "$REPLY" != "y" ] || 
echo "about to auto-commit any changes"
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  echo "Creating backup auto-save branch: auto-save-$branchname-at-$timestamp"
  git branch "auto-save-$branchname-at-$timestamp" 
fi
echo "now resetting to origin/$branchname"
git fetch origin
git reset --hard origin/$branchname
Andrew Tulloch
fuente
3
es posible que desee utilizar "git remote" para obtener el nombre del control remoto. En ciertos casos, no será "origen"
Yurik
17

Siempre que el repositorio remoto sea origin, y que le interese branch_name:

git fetch origin
git reset --hard origin/<branch_name>

Además, debe restablecer la rama actual de origina HEAD.

git fetch origin
git reset --hard origin/HEAD

Cómo funciona:

git fetch origin descarga lo último desde el control remoto sin intentar fusionar o volver a crear nada.

Luego git resetrestablece la <branch_name>rama a lo que acaba de obtener. La --hardopción cambia todos los archivos en su árbol de trabajo para que coincidan con los archivos origin/branch_name.

eigenharsha
fuente
14

Yo hice:

git branch -D master
git checkout master

restablecer totalmente la rama


tenga en cuenta que debe pagar a otra sucursal para poder eliminar la sucursal requerida

usuario2846569
fuente
55
Debería leer la pregunta una vez más, no hay nada en afectar el control remoto, sino configurarlo como remoto, por lo que no debe hacer nada con el control remoto, y esto ayudó en mi caso y no en lo anterior.
user2846569
Si desea configurarlo de la misma manera que el control remoto, al menos debería buscarlo en algún momento, ¿no está de acuerdo?
Tim
2
al menos deberías probar esto o leer documentos: kernel.org/pub/software/scm/git/docs/git-checkout.html
user2846569
Muy bien, tenía un archivo .pck corrupto en la rama y el resto de las opciones no funcionaban, ¡gracias!
LuckyBrain
14

Aquí hay un script que automatiza lo que sugiere la respuesta más popular ... Consulte https://stackoverflow.com/a/13308579/1497139 para obtener una versión mejorada que admite sucursales

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# see /programming/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  git branch "auto-save-at-$timestamp" 
fi
git fetch origin
git reset --hard origin/master
Wolfgang Fahl
fuente
10

Si tuvo un problema como yo, que ya ha cometido algunos cambios, pero ahora, por cualquier motivo que desee deshacerse de él, la forma más rápida es usarlo git resetasí:

git reset --hard HEAD~2

Tenía 2 commits no necesarios, de ahí el número 2. Puede cambiarlo a su propio número de commits para restablecer.

Entonces, responda su pregunta: si tiene 5 confirmaciones por delante del repositorio remoto HEAD, debe ejecutar este comando:

git reset --hard HEAD~5

Tenga en cuenta que perderá los cambios que ha realizado, ¡así que tenga cuidado!

Karol
fuente
7

Las respuestas anteriores suponen que la rama a restablecer es la rama actual (desprotegida). En los comentarios, OP hap497 aclaró que la rama está desprotegida, pero la pregunta original no lo requiere explícitamente. Como hay al menos una pregunta "duplicada", restablezca la rama completamente al estado del repositorio , lo que no supone que la rama esté desprotegida, aquí hay una alternativa:

Si la rama "mybranch" no está actualmente desprotegida, para restablecerla a la cabeza de la rama remota "myremote / mybranch", puede usar este comando de bajo nivel :

git update-ref refs/heads/mybranch myremote/mybranch

Este método deja la rama desprotegida como está y el árbol de trabajo intacto. Simplemente mueve la cabeza de mybranch a otra confirmación, lo que sea que se dé como segundo argumento. Esto es especialmente útil si es necesario actualizar varias ramas a nuevos cabezales remotos.

Sin embargo, tenga cuidado al hacer esto, y use gitko una herramienta similar para verificar el origen y el destino. Si accidentalmente hace esto en la rama actual (y git no lo mantendrá alejado de esto), puede confundirse, porque el contenido de la nueva rama no coincide con el árbol de trabajo, que no cambió (para corregir, actualizar la rama nuevamente, a donde estaba antes).

Rainer Blome
fuente
7

Esto es lo que uso a menudo:

git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;

Tenga en cuenta que es una buena práctica de no hacer cambios a su maestro local / desarrollar rama, pero en lugar de pagar a otra rama para cualquier cambio, con el nombre de la sucursal antepuesto por el tipo de cambio, por ejemplo feat/, chore/, fix/, etc. De esta manera sólo se necesitan tire de los cambios, no empuje ningún cambio desde el maestro. Lo mismo para otras ramas a las que otros contribuyen. Por lo tanto, lo anterior solo debe usarse si ha cometido cambios en una rama a la que otros se han comprometido y necesita restablecerse. De lo contrario, en el futuro, evite presionar a una rama a la que otros presionan, en lugar de pagar y enviar a dicha rama a través de la rama desprotegida.

Si desea restablecer su sucursal local a la última confirmación en la rama ascendente, lo que funciona para mí hasta ahora es:

Verifique sus controles remotos, asegúrese de que su origen y origen sean lo que espera, si no es como se esperaba, use git remote add upstream <insert URL>, por ejemplo, el repositorio original de GitHub del que bifurcó, y / o git remote add origin <insert URL of the forked GitHub repo>.

git remote --verbose

git checkout develop;
git commit -m "Saving work.";
git branch saved-work;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force

En GitHub, también puede pagar la rama con el mismo nombre que la local, para guardar el trabajo allí, aunque esto no es necesario si el desarrollo de origen tiene los mismos cambios que la rama local de trabajo guardado. Estoy usando la rama de desarrollo como ejemplo, pero puede ser cualquier nombre de rama existente.

git add .
git commit -m "Reset to upstream/develop"
git push --force origin develop

Luego, si necesita fusionar estos cambios con otra rama mientras existen conflictos, preservando los cambios en el desarrollo, use:

git merge -s recursive -X theirs develop

Mientras uso

git merge -s recursive -X ours develop

para preservar los cambios conflictivos de branch_name. De lo contrario, use una herramienta de combinación con git mergetool.

Con todos los cambios juntos:

git commit -m "Saving work.";
git branch saved-work;
git checkout develop;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;
git add .;
git commit -m "Reset to upstream/develop";
git push --force origin develop;
git checkout branch_name;
git merge develop;

Tenga en cuenta que en lugar de upstream / desarrollo, podría usar un hash de confirmación, otro nombre de rama, etc. Use una herramienta CLI como Oh My Zsh para verificar que su rama sea verde, lo que indica que no hay nada que confirmar y que el directorio de trabajo está limpio ( que es confirmado o también verificable por git status). Tenga en cuenta que esto puede agregar realmente compromete en comparación a aguas arriba a desarrollar si hay algo añadido automáticamente por un commit, por ejemplo, diagramas UML, cabeceras de licencia, etc., por lo que en ese caso, se podría entonces tirar de los cambios en la origin developque upstream develop, si es necesario.

James Ray
fuente
6

La respuesta

git clean -d -f

fue subestimado ( -d para eliminar directorios). ¡Gracias!

Anael
fuente
Y para una carpeta de repositorio completa y 100% limpia sin archivos adicionales, ejecute git clean -xdf. Esto eliminará todos y cada uno de los archivos que git desconoce, y hará que su carpeta coincida exactamente con lo que está en la lista de objetos de git. Tenga en cuenta que puede agregar -n(p git clean -nxdf. Ej. ) Para realizar un "qué pasaría si" y le dirá qué eliminará sin realmente hacer nada. ( git clean )
qJake
5

Si desea volver al HEADestado del directorio de trabajo y del índice, debería hacerlo git reset --hard HEAD, en lugar de hacerlo HEAD^. (Esto puede haber sido un error tipográfico, al igual que para el guión simple versus doble --hard).

En cuanto a su pregunta específica de por qué esos archivos aparecen en el estado modificado, parece que quizás hizo un restablecimiento parcial en lugar de un restablecimiento completo. Esto hará que los archivos que se modificaron en la HEADconfirmación aparezcan como si estuvieran en escena, lo que probablemente es lo que está viendo aquí.

Emil Sit
fuente
4

Ninguna cantidad de reinicio y limpieza pareció tener ningún efecto en los archivos no rastreados y modificados en mi repositorio git local (probé todas las opciones anteriores). Mi única solución a esto fue confirmar el repositorio local y volver a clonarlo desde el control remoto.

Afortunadamente no tenía otras ramas que me importaran.

xkcd: Git

Martín
fuente
1

La única solución que funciona en todos los casos que he visto es eliminar y volver a colocar. Tal vez hay otra forma, pero obviamente de esta manera no hay posibilidad de que el viejo estado se quede allí, así que lo prefiero. Bash one-liner puede establecer como macro si a menudo arruina las cosas en git:

REPO_PATH=$(pwd) && GIT_URL=$(git config --get remote.origin.url) && cd .. && rm -rf $REPO_PATH && git clone --recursive $GIT_URL $REPO_PATH && cd $REPO_PATH

* asume que tus archivos .git no están dañados

sudo
fuente
44
¡también puedes reinstalar tu sistema operativo si quieres estar seguro!
Sebastian Scholle
1

¿Has olvidado crear una rama de características y te has comprometido directamente en master por error?

Puede crear la rama de características ahora y volver a configurar el maestro sin afectar el árbol de trabajo (sistema de archivos local) para evitar generar compilaciones, pruebas y problemas con los bloqueos de archivos:

git checkout -b feature-branch
git branch -f master origin/master
Grastveit
fuente
1

Solo 3 comandos lo harán funcionar

git fetch origin
git reset --hard origin/HEAD
git clean -f
Nirmal profundo
fuente
-3

Si no le importa guardar sus cambios locales, pero aún así desea actualizar su repositorio para que coincida con el origen / HEAD, simplemente puede esconder sus cambios locales y luego extraer:

git stash
git pull
Micah Walter
fuente