¿Cómo reemplazar una sucursal local con una sucursal remota por completo en Git?

779

Tengo dos ramas:

  1. sucursal local (con la que trabajo)
  2. rama remota (público, solo los commits bien probados van allí)

Recientemente arruiné seriamente mi sucursal local.

¿Cómo reemplazaría la sucursal local por completo con la remota, para poder continuar mi trabajo desde donde está la sucursal remota ahora?

Ya he buscado SO y salir de la sucursal remota localmente no tiene ningún efecto.

YemSalat
fuente
1
Sé que la respuesta aceptada tiene 1280 votos positivos, pero realmente deberías considerar cambiar la respuesta aceptada por @TTT.
Jamie

Respuestas:

1289
  1. Asegúrate de haber revisado la rama que estás reemplazando (del comentario de Zoltán ).
  2. Asumiendo que master es la rama local que está reemplazando, y que "origin / master" es la rama remota a la que desea restablecer:

    git reset --hard origin/master
    

Esto actualiza su rama HEAD local para que tenga la misma revisión que origin / master, y --hardtambién sincronizará este cambio en el índice y el espacio de trabajo.

araqnid
fuente
44
Gracias por su sugerencia, ya estoy tan 'asustado' de usar --hard y --force ya, así que elegí la solución que no los usa.
YemSalat
13
@ KonstantinLevin: ah sí, nombrar esas opciones es bastante irritante. git resetde forma predeterminada, volverá a señalar su rama actual y sincronizará el índice. --softomitirá la actualización del índice, --hardtambién sincronizará el espacio de trabajo. Mi propia experiencia es usar la --hardmayor parte del tiempo, excepto cuando quiero deshacer el último commit (que es solo git reset HEAD^)
araqnid
99
Después de tener más experiencia con git, estoy convencido de que esta es una mejor solución, gracias.
YemSalat
24
probablemente tendrá que buscar primero:git fetch origin remote_branch
b1r3k
53
Debe tener en cuenta que esto reemplazará cualquier rama en la que se encuentre actualmente con el contenido del maestro . Entonces, si está en, por ejemplo, una rama de características, reemplazará todas sus confirmaciones master, así que asegúrese de haber verificado primero la rama que está reemplazando.
Zoltán
218

Eso es tan fácil como tres pasos:

  1. Eliminar su sucursal local: git branch -d local_branch
  2. Obtenga la última rama remota: git fetch origin remote_branch
  3. Reconstruya la rama local basada en la remota: git checkout -b local_branch origin/remote_branch
Adam Smith
fuente
77
En realidad, lo que dijo @araqnid es correcto y más conciso. Lo he probado y puedes probarlo también.
adamsmith
¡Guau, el git checkout -b local_branch origin / remote_branch es genial! Siempre hice esto en dos comandos separados. ¡Gracias!
kendepelchin
11
Es posible que deba hacerlo git branch -D local_branchen el primer paso si su rama no está fusionada.
szeryf
gracias, me costó mucho usar gitflow, después de publicar una rama y luego terminarla, quería ir a la rama eliminada, y su solución fue la única que funcionó, pull parece que no funciona ... o lo hice no lo he usado bien -
Decébal
2
debemos asegurarnos de que la rama actual no sea la que se va a eliminar.
a_secenthusiast
43
git branch -D <branch-name>
git fetch <remote> <branch-name>
git checkout -b <branch-name> --track <remote>/<branch-name>
Sailesh
fuente
¿Qué hace la parte --track?
eonista
3
@GitSync, esto es lo que git help branchdice --track. When creating a new branch, set up branch.<name>.remote and branch.<name>.merge configuration entries to mark the start-point branch as "upstream" from the new branch. This configuration will tell git to show the relationship between the two branches in git status and git branch -v. Furthermore, it directs git pull without arguments to pull from the upstream when the new branch is checked out. Arreglé este comando en la respuesta. Gracias por plantear el punto.
Sailesh
Entonces, en términos simples: agrega la URL remota a la nueva rama. Entonces están sincronizados para siempre. Por así decirlo.
eonista
2
Puedes decir que es solo por conveniencia. Si lo hace git status, informará si su sucursal local está adelante o detrás de la sucursal remota si los tiene asociados. Además, puede hacer git pull(o push) en lugar de completar git pull <remote> <branch>si ya ha configurado su rama para realizar un seguimiento <remote/branch>.
Sailesh
22

Reemplace todo con la rama remota; pero , solo desde el mismo compromiso, su sucursal local está activada:

git reset --hard origin/some-branch

O , obtenga lo último de la rama remota y reemplace todo:

git fetch origin some-branch
git reset --hard FETCH_HEAD

Por otro lado, si es necesario, puede borrar los archivos y directorios no rastreados que aún no ha confirmado:

git clean -fd
un poco menos
fuente
El git cleancomando lo hizo por mí. git reset hard origin/masterno borre los archivos no rastreados. ¡Gracias!
Mornor
9

La forma más segura y completa de reemplazar la sucursal local actual con el control remoto:

git stash
git merge --abort
git rebase --abort
git branch -M yourBranch replaced_yourBranch
git fetch origin yourBranch:yourBranch
git checkout yourBranch

La stashlínea guarda los cambios que no ha confirmado. La branchlínea mueve su rama a un nombre diferente, liberando el nombre original. La fetchlínea recupera la última copia del control remoto. La checkoutlínea recrea la rama original como una rama de seguimiento.

O como una función bash:

replaceWithRemote() {
    yourBranch=${1:-`git rev-parse --abbrev-ref HEAD`}
    git stash
    git merge --abort
    git rebase --abort
    git branch -M ${yourBranch} replaced_${yourBranch}_`git rev-parse --short HEAD`
    git fetch origin ${yourBranch}:${yourBranch}
    git checkout ${yourBranch}
}

que cambia el nombre de la rama actual a algo como reemplazado_master_98d258f.

Joshua S
fuente
Es posible que desee incluir git stash popen ese flujo de trabajo. Si desea volver a aplicar sus archivos escondidos.
eonista
¿Qué haces con la rama escondida? Me temo que volverá a aparecer en algún lugar en el futuro mucho después de que haya olvidado para qué era.
Scott Biggs
1
@ScottBiggs Si desea eliminar la rama escondida, use "git stash clear".
Mark A. Durham
5

Estoy un poco sorprendido de que nadie haya mencionado esto todavía; Lo uso casi todos los días:

git reset --hard @{u}

Básicamente, @{u}es solo una abreviatura de la rama ascendente que su rama actual está rastreando. Por ejemplo, esto generalmente equivale a origin/[my-current-branch-name]. Es agradable porque es independiente de la rama.

Asegúrese git fetchde obtener primero la última copia de la rama remota.

TTT
fuente
1
eso se ve muy bien, ¡me cansé de copiar y pegar el nombre de la rama para restablecer!
pedroct92
1
Tuve algunas instancias en las que agregué respuestas a viejas preguntas, y mis respuestas subieron en la clasificación. Espero que este lo haga.
Jamie
3

Se puede hacer de varias maneras, continuando editando esta respuesta para difundir una mejor perspectiva de conocimiento.

1) Restablecer duro

Si está trabajando desde la rama de desarrollo remoto, puede restablecer HEAD a la última confirmación en la rama remota de la siguiente manera:

git reset --hard origin/develop

2) Eliminar la rama actual y volver a pagar desde el repositorio remoto

Teniendo en cuenta que está trabajando en la sucursal de desarrollo en el repositorio local, que se sincroniza con la sucursal remota / de desarrollo, puede hacer lo siguiente:

git branch -D develop
git checkout -b develop origin/develop

3) Abortar fusión

Si está en medio de una fusión incorrecta (por error, con una rama incorrecta), y desea evitar la fusión para volver a la última rama como se muestra a continuación:

git merge --abort

4) Cancelar base

Si está en medio de un rebase incorrecto, puede cancelar la solicitud de rebase de la siguiente manera:

git rebase --abort
Amit Kaneria
fuente
2

Puede hacer lo que @Hugo de @Laurent dijo, o puede usar git rebasepara eliminar las confirmaciones que desea eliminar, si sabe cuáles. Tiendo a usar git rebase -i head~N(donde N es un número, lo que le permite manipular los últimos N commits) para este tipo de operaciones.

ksol
fuente
En realidad, fue el comando 'git rebase' lo que arruinó todo el asunto, luego algunas fusiones forzadas y restablecimientos duros ... De todos modos, lo que estaba buscando es una forma fácil de extraer todo el repositorio del servidor remoto sin fusionarlo.
YemSalat
2

La respuesta seleccionada es absolutamente correcta , sin embargo, no me dejó con los últimos commit / push ...

Entonces para mi:

git reset --hard dev/jobmanager-tools
git pull  ( did not work as git was not sure what branch i wanted)

Como sé que quiero configurar temporalmente mi rama ascendente durante unas semanas en una rama específica (igual a la que cambié / verifiqué anteriormente e hice un restablecimiento completo)

Entonces DESPUÉS de reiniciar

git branch --set-upstream-to=origin/dev/jobmanager-tools
git pull
git status    ( says--> on branch  dev/jobmanager-tools 
Tom Stickel
fuente
1

Si desea actualizar la sucursal que no está actualmente desprotegida, puede hacer lo siguiente:

git fetch -f origin rbranch:lbranch
kqr
fuente
0

Como se proporciona en la explicación elegida, git reset es bueno. Pero hoy en día a menudo utilizamos submódulos: repositorios dentro de repositorios. Por ejemplo, si usa ZF3 y jQuery en su proyecto, lo más probable es que desee que se clonen de sus repositorios originales. En tal caso, git reset no es suficiente. Necesitamos actualizar submódulos a esa versión exacta que se define en nuestro repositorio:

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

git submodule foreach git submodule update

git status

es lo mismo que vendrá (cd) recursivamente al directorio de trabajo de cada submódulo y ejecutará:

git submodule update

Y es muy diferente de

git checkout master
git pull

porque los submódulos no apuntan a la ramificación sino a la confirmación.

En esos casos, cuando desprotege manualmente alguna rama para 1 o más submódulos, puede ejecutar

git submodule foreach git pull
Eugene Kaurov
fuente
Proporcione una explicación, especialmente cuando responda preguntas tan antiguas. Su respuesta no es útil como está.
Erik A
La respuesta aceptada ya propone git reset --hard. Esto agrega poco valor.
florisla
0
git reset --hard
git clean -fd

Esto funcionó para mí: clean también mostró todos los archivos que eliminó. Si te dice que perderás los cambios, debes esconderte.

Travis Heeter
fuente
-6

La forma fea pero más simple: elimine su carpeta local y clone el repositorio remoto nuevamente.

Hugo
fuente
10
O simplemente elimine la rama y revísela nuevamente.
Laurent
Sí, supongo que eso es lo que voy a hacer si no encuentro cómo hacerlo de una manera menos 'fea'
YemSalat
2
Feo a veces es útil saberlo. Desearía que la gente no rechazara las cosas solo porque no son la forma convencional: debe haber una razón más racional para la votación negativa ... y debe darse. Git es una cosa que logra resultados. No es una especie de texto sagrado.
Mike roedor
3
No entiendo los votos negativos :-( Sí, no es elegante, etc. pero puede funcionar mejor en algunos casos ... lo siento @Hugo
silverdr
@Hugo, de acuerdo. Algo misterioso y maloliente le sucedió a mi sucursal de desarrollo local, y tanto el Jefe de Equipo como el Gerente de Ingeniería sugirieron, entre otras soluciones más elegantes, simplemente (comprimir, copiar y guardar mi trabajo de características, luego) bombardear el repositorio local y reclinar.
AmitaiB