Necesita restablecer git branch a la versión de origen

440

Estaba trabajando accidentalmente en una rama que no debería haber estado durante un tiempo, así que me separé dándole el nombre apropiado. Ahora quiero sobrescribir la rama en la que no debería haber estado en la versión desde el origen (github). ¿Hay una forma fácil de hacer esto? Intenté eliminar la rama y luego restablecer la rama de seguimiento, pero solo me da la versión en la que estaba trabajando nuevamente.

Brad Herman
fuente
Con Git 2.23 (agosto de 2019): git switch -C mybranch origin/mybranch. Vea mi respuesta editada a continuación
VonC

Respuestas:

816

Si aún no ha llegado al origen, puede restablecer su rama a la rama ascendente con:

git checkout mybranch
git reset --hard origin/mybranch

(Asegúrese de hacer referencia a su último commit en una rama separada, como menciona en su pregunta)

Tenga en cuenta que justo después del reinicio, se mybranch@{1}refiere a la confirmación anterior, antes del reinicio.

Pero si ya había presionado, consulte " Crear rama git y revertir el original al estado ascendente " para ver otras opciones.


Con Git 2.23 (agosto de 2019) , que sería un comando: git switch.
A saber:git switch -C mybranch origin/mybranch

Ejemplo

C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.

Eso restaura el índice y el árbol de trabajo, como lo git reset --hardharía.


Como se ha comentado por Brad Herman , una reset --hardsería eliminar cualquier archivo nuevo o modificado archivos vuelva a CABEZA .

En realidad, para asegurarse de comenzar desde una "pizarra limpia", un git clean -f -ddespués del reinicio garantizaría un árbol de trabajo exactamente idéntico a la rama a la que acaba de reiniciar.


Esta publicación de blog sugiere esos alias ( mastersolo para rama, pero puede adaptarlos / extenderlos):

[alias]
   resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
   resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d

Entonces puedes escribir:

git resetupstream

o

git resetorigin
VonC
fuente
26
esto ELIMINARÁ los cambios NO FIJADOS / ESCENARIOS (desde --hard)
Peter Ehrlich
55
He usado el git reset --hard origin/mybranchcomando varias veces cuando no me importaban los cambios locales y solo quería una copia limpia que coincidiera con el origen. Sin embargo, hoy, esto no funcionó: todavía tenía un puñado de archivos nuevos sin clasificar, y git seguía prometiéndome que estaba en HEAD. La nota sobre lo git clean -f -dsolucionó borrando todos los archivos nuevos que no quería.
Matthew Clark el
@MatthewClark Eso se espera: ver comentario en stackoverflow.com/q/4327708/6309
VonC
1
¡Excelente! También muchas veces solía git reset --hard HEADvolver a una confirmación anterior, ignorando cualquier cambio
daronwolff
¿Es esto posible también con sourctree?
Lonzak
20

Asumiendo que esto es lo que sucedió:

# on branch master
vi buggy.py                 # you edit file
git add buggy.py            # stage file
git commit -m "Fix the bug" # commit
vi tests.py                 # edit another file but do not commit yet

Entonces te das cuenta de que haces cambios en la rama equivocada.

git checkout -b mybranch    # you create the correct branch and switch to it

Pero masteraún apunta a su compromiso. Desea que apunte hacia donde apuntó antes.

Solución

La forma más fácil es:

git branch --force master origin/master

Otra forma es:

git checkout master
git reset --soft origin/master
git checkout mybranch

Tenga en cuenta que el uso reset --hardhará que se pierdan los cambios no confirmados ( tests.pyen mi ejemplo).

usuario28667
fuente
Eso parece más seguro que en mi respuesta;) +1
VonC
8

Tengo un repositorio privado en un servidor y regularmente lo reescribo / forzo, lo que hace que sea necesario restablecer la rama local en mi otra computadora con frecuencia. Por lo tanto, creé el siguiente alias "catchup", que permite hacer esto para la rama actual. A diferencia de la otra respuesta, no hay un nombre de rama codificado en este alias.

Agárrate fuerte.

[alias]
  catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"

Formateado correctamente (no funcionará con las nuevas líneas en .gitconfig) se ve así:

"
!f(){
  echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
  read -r ans;
  if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
    git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
  else
    echo \"catchup aborted\";
  fi
}; f
"
  • El \\033[0;33my \\033[0mes para enfatizar la rama actual y corriente arriba con color.
  • $(git symbolic-ref -q --short HEAD) es el nombre actual de la sucursal
  • $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) es el flujo ascendente de la rama actual.

Dado que restablecer es una llamada potencialmente peligrosa (especialmente con la opción --hard, perderá los cambios no confirmados), primero le indica lo que está por hacer. Por ejemplo, si está en una rama dev-container con control remoto llamado qcpp / dev-container e ingresa git catchup, se le pedirá:

restablecer dev-container a qcpp / dev-container? (S / n)

Si luego escribe y o simplemente presiona regresar, realizará el reinicio. Si ingresa algo más, el reinicio no se llevará a cabo.

Si desea ser súper seguro y prevenir mediante programación la pérdida de cambios no organizados / no confirmados, puede aumentar aún más el alias anterior con las comprobaciones correspondientes para el índice de diferencias .

La palabra de advertencia obligatoria: si está trabajando en un repositorio público en el que otras personas han basado su trabajo y necesita este alias, lo está haciendo mal ™ .

DerManu
fuente
1

Intenté esto y no restableció mi rama actual a mi github remoto más reciente. Busqué en Google y encontré https://itsyndicate.org/blog/how-to-use-git-force-pull-properly/

que sugirió

git fetch origin master
git reset --hard origin/master

Quería restablecer mi rama v8, así que lo hice

git fetch origin v8
git reset --hard origin/v8

Y funcionó

SimpleSi
fuente
Bueno, es bueno que menciones fetch. Lo hice una vez sin y restablecí todo a hace 2 años :)
Adam