Restablecer el control remoto a una determinada confirmación

709

Quiero descartar todos los cambios realizados después de la confirmación <commit-hash>. Así que lo hice:

git reset --hard <commit-hash>

Ahora quiero hacer lo mismo con mi control remoto. ¿Cómo puedo hacer esto? He realizado algunos commits (y empujones) después <commit-hash>y solo quiero descartarlos a todos. Es que algo salió terriblemente mal en el camino y no quiero empeorarlo más de lo que ya está. ; (

Básicamente quiero mi rebobinar origin/mastera<commit-hash>

nacho4d
fuente
3
¿Estás seguro origin/masterde que otros usuarios no te han tirado y empujado? Cambiar el historial de un repositorio público (es decir, no local) es algo que desea evitar en todo momento.
vindia
Posible duplicado de ¿Cómo revertir múltiples confirmaciones de git?
Michael Freidgeim

Respuestas:

1252

Suponiendo que su rama se llama mastertanto aquí como remotamente, y que su control remoto se llama origin, puede hacer lo siguiente:

 git reset --hard <commit-hash>
 git push -f origin master

Sin embargo, debe evitar hacer esto si alguien más está trabajando con su repositorio remoto y ha retirado sus cambios. En ese caso, sería mejor revertir las confirmaciones que no desea y luego presionar de manera normal.

Actualización: ha explicado a continuación que otras personas han eliminado los cambios que ha introducido, por lo que es mejor crear una nueva confirmación que revierta todos esos cambios . Hay una buena explicación de sus opciones para hacer esto en esta respuesta de Jakub Narębski . Cuál es más conveniente depende de cuántas confirmaciones desea revertir y qué método tiene más sentido para usted.

Como de su pregunta está claro que ya ha utilizado git reset --hardpara restablecer su mastersucursal, es posible que deba comenzar a usar git reset --hard ORIG_HEADpara mover su sucursal a donde estaba antes. (Como siempre con git reset --hard, asegúrese de que git statusesté limpio, que esté en la rama correcta y que sea consciente de que git refloges una herramienta para recuperar confirmaciones aparentemente perdidas). También debe verificar que ORIG_HEADapunta a la confirmación correcta, con git show ORIG_HEAD.

Solución de problemas:

Si recibe un mensaje como " ! [Control remoto rechazado] a60f7d85 -> maestro (gancho previo a la recepción rechazado) "

entonces debe permitir la reescritura del historial de sucursal para la sucursal específica. En BitBucket, por ejemplo, decía "No se permite reescribir el historial de sucursales". Hay una casilla de verificación llamada Allow rewriting branch historyque debe marcar.

Mark Longair
fuente
21
Peligro de peligro: este reinicio asume que la rama correspondiente ( seguimiento ) está actualmente desprotegida y no hay cambios no confirmados que desea conservar. Usar en git update-reflugar dereset --hard ; le permitirá hacer lo mismo sin tener un árbol en funcionamiento / rama desprotegida
sehe
3
Veo. Ha sido empujado y cambiado por otros. Entonces debería usar, revert pero digamos que quiero revertir los últimos 4 commits, ¿debería hacerlo git revert comit1; git push; git revert comit2; git push; ...o simplemente git revert commit4; git push?
nacho4d
1
@ nacho4d: no es necesario presionar después de cada reversión: hay una buena descripción de qué hacer en esta respuesta de Jakub Narębski . Es necesario revertir cada confirmación yendo hacia atrás; solo hacerlo git revert commit4crea una nueva confirmación que solo deshace los cambios que se introdujeron commit4. Sin embargo, como señala la respuesta a la que he vinculado, puede incluirlos en una sola confirmación.
Mark Longair
1
@ Mark Ya lo he ejecutado, git reset --hardpero he eliminado mi local y lo saqué del origen nuevamente, así que puedo hacerlo. git revert ...Mi duda ahora es: ¿tengo que revertir cada confirmación y presionar (una por una) o simplemente revertir la primera confirmación después del derecho cometer solo?
nacho4d
1
@sehe: es difícil de usar porque necesitas usar el nombre completo de la referencia, por lo que es fácil para las personas llenar su .gitdirectorio con referencias que no querían crear. Sin embargo, me equivoqué al decir que no hay controles de seguridad. Puede encontrar la clasificación en comandos de "plomería" y "porcelana" en la página de manual de git .
Mark Longair
123

Use las otras respuestas si no le importa perder los cambios locales. Este método aún puede destruir su control remoto si elige el hash de confirmación incorrecto para volver.

Si solo desea que el control remoto coincida con una confirmación que esté en cualquier parte de su repositorio local:

  1. No no hacer ningún reajuste.
  2. Use git logpara encontrar la confirmación que desea que tenga el control remoto. git log -ppara ver cambios o git log --graph --all --oneline --decoratepara ver un árbol compacto.
  3. Copie el hash del commit o su etiqueta, o el nombre de su rama si es la punta.
  4. Ejecute un comando como:

    git push --force <remote> <commit-ish>:<the remote branch>
    

    p.ej

    git push --force origin 606fdfaa33af1844c86f4267a136d4666e576cdc:master
    

    o

    git push --force staging v2.4.0b2:releases
    

Utilizo el alias conveniente ( git go) para ver el historial como en el paso 2, que se puede agregar así:

    git config --global alias.go 'log --graph --all --decorate --oneline'`
Walf
fuente
3
El gráfico fue un consejo muy bueno, solo agregué -5 para obtener solo los últimos n commits, era un árbol enorme más. También evitar el reinicio es justo lo que estaba buscando. Genial
AlexanderD
@AlexanderD También puede agregar el alias a Git en lugar de su shell, para que funcione en todas partes. Git comprende esos alias y tabulaciones completas del comando completo para que pueda agregar argumentos. git config --global alias.graph 'log --graph --all --decorate --oneline'es menos desordenado y todavía puede limitarlo, por ejemplo:git graph -5
Walf
Esto es perfecto. Siempre he estropeado mi local. Esto fue exactamente lo que necesitaba después de accidentalmente empujar mi puesta en escena para vivir :( ¡Gracias!
Jake
1
En Windows, ingrese qpara salir del registro git. 2 minutos nunca volveré.
dst3p
1
@ dst3p Eso está en todas las plataformas, amigo. El programa de buscapersonas suele ser lessy qes la forma normal de salir de él. Git Bash es como un terminal * nix.
Walf
63

Resolví problemas como el tuyo con estos comandos:

git reset --hard <commit-hash> 
git push -f <remote> <local branch>:<remote branch> 
Ibrohim Ermatov
fuente
13

En GitLab, es posible que deba configurar su rama como desprotegida antes de hacer esto. Puede hacerlo en [repo]> Configuración> Repositorio> Ramas protegidas. Entonces el método de la respuesta de Mark funciona.

git reset --hard <commit-hash>
git push -f origin master
dudasaus
fuente
10

Si desea una versión anterior del archivo, le recomendaría usar git checkout.

git checkout <commit-hash>

Hacer esto te devolverá en el tiempo, no afecta el estado actual de tu proyecto, puedes ir a mainline git checkout mainline

pero cuando agrega un archivo en el argumento, ese archivo se le devuelve desde una hora anterior a la hora actual de su proyecto, es decir, su proyecto actual se modifica y debe confirmarse.

git checkout <commit-hash> -- file_name
git add .
git commit -m 'file brought from previous time'
git push

La ventaja de esto es que no elimina el historial y tampoco revierte los cambios de un código en particular (git revert)

Consulte más aquí https://www.atlassian.com/git/tutorials/undoing-changes#git-checkout

priya khokher
fuente
Esta es una excelente respuesta: funciona, punto y es muy seguro; Si lo arruinas, es fácil volver.
bob
8

Mis dos centavos a las respuestas anteriores: si

git push --force <remote> <the-hash>:<the remote branch>

todavía no funciona, es posible que desee editar <your-remote-repo>.git/configla sección de recepción del archivo:

[receive]
  #denyNonFastforwards = true
  denyNonFastforwards = false
obispo
fuente
Es útil saber cómo configurar un control remoto para permitir empujes que no avancen rápidamente ya que la mayoría de las respuestas parecen asumir un servicio remoto como github o bitbucket.
strongbutgood
2

Si su sucursal no es desarrollo o producción, la forma más fácil de lograr esto es restablecer un determinado compromiso localmente y crear una nueva sucursal desde allí. Puedes usar:

git checkout 000000

(donde 000000 es la identificación de confirmación donde desea ir) en su rama problemática y luego simplemente cree una nueva rama:

git remote add [nombre_de_su_remoto]

¡Entonces puedes crear un nuevo PR y todo funcionará bien!

Gerardo Suárez
fuente
1

Haz una cosa, obtén el SHA del commit no. como 87c9808 y luego,

  1. muévete, esa es tu cabeza al commit especificado (haciendo git reset --hard 89cef43 // menciona tu número aquí)
  2. A continuación, realice algunos cambios en un archivo aleatorio, de modo que el git le pida que lo confirme localmente y luego de forma remota. Por lo tanto, lo que debe hacer ahora es. después de aplicar change git commit -a -m "trial commit"
  3. Ahora empuje la siguiente confirmación (si esto se ha confirmado localmente) por git push origin master
  4. Ahora lo que git te pedirá es que

error: no se pudieron insertar algunas referencias a ' https://github.com/YOURREPOSITORY/AndroidExperiments.git ' sugerencia: se rechazaron las actualizaciones porque la punta de su rama actual está detrás de la sugerencia: su contraparte remota. Integre los cambios remotos (por ejemplo, pista: 'git pull ...') antes de presionar nuevamente. **

  1. Por lo tanto, ahora lo que puedes hacer es

git push --force origin master

  1. Y así, espero que funcione :)
Siddharth Choudhary
fuente
1

Sourcetree: restablecer el control remoto a una determinada confirmación

  1. Si ha enviado una confirmación incorrecta a su control remoto (origen / función / 1337_MiAwesomeFeature) como en la imagen de abajo

Ir a controles remotos

  1. Vaya a Controles remotos> origen> función> 1337_MyAwesomeFeature
  2. Haga clic con el botón derecho y elija "Eliminar origen / función / 1337_MyAwesomeFeature" (o cambie el nombre si desea una copia de seguridad y omita el paso 4.)
  3. Haga clic en "Forzar eliminación" y "Aceptar".

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

  1. Seleccione su confirmación anterior y elija "Restablecer la rama actual a esta confirmación"
  2. Elija el modo que desea tener (Difícil si no desea sus últimos cambios) y "Aceptar".

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

  1. Empuje esta confirmación a un nuevo origen / característica / 1337_MyAwesomeFeature ingrese la descripción de la imagen aquí

  2. Su rama de características local y su rama de características remotas ahora están en el compromiso anterior (de su elección) ingrese la descripción de la imagen aquí

Joel Wiklund
fuente