¿Cómo restaurar / repetir la sincronización después de que alguien haga clic en una rebase o reinicie en una rama publicada?

Todos escuchamos que nunca debes reinstalar el trabajo publicado, es peligroso, etc. Sin embargo, no vi las recetas publicadas sobre cómo hacer frente a la situación en el caso de publicar una permutación.

Ahora note que esto es real solo si el repositorio es clonado solo por un grupo de personas conocidas (y preferiblemente pequeñas), por lo que cualquier persona que presione una rebase o reinicio puede notificar a todos los demás que deberán prestar atención la próxima vez que extraerá (!).

Una solución obvia que vi funcionará si no tiene confirmaciones locales en foo , y se vuelve a basar:

 git fetch git checkout foo git reset --hard origin/foo 

Esto simplemente arroja el estado local de foo en favor de su historia en el repositorio remoto.

Pero, ¿cómo hace frente a la situación si hay cambios locales significativos en este hilo?

74
03 нояб. puesta por Aristóteles Pagaltzis 03 nov. 2010-11-03 10:08 '10 a las 10:08 2010-11-03 10:08
@ 3 respuestas

Volver a sincronizar después de una transferencia arrastrada realmente no es tan difícil en la mayoría de los casos.

 git checkout foo git branch old-foo origin/foo # BEFORE fetching!! git fetch git rebase --onto origin/foo old-foo foo git branch -D old-foo 

Es decir primero creó un marcador en el que originalmente se encontraba la rama remota, luego lo usa para reproducir sus confirmaciones locales desde este punto a la rama remota.

Rebasar es como la violencia: si no resuelve tu problema, solo necesitas más. ☺

Por supuesto, puede hacer esto sin un marcador si observa el identificador de origin/foo fix anterior a la rebase y lo utiliza.

Esta es también la forma en que maneja la situación cuando olvidó marcar como favorito antes de finalizar la compra. No se pierde nada: solo tiene que comprobar el reflog de la rama remota:

 git reflog show origin/foo | awk ' PRINT_NEXT==1 { print $1; exit } /fetch: forced-update/ { PRINT_NEXT=1 }' 

Esto imprimirá el identificador de corrección especificado por origin/foo justo antes del extracto más reciente que cambió su historial.

Entonces puedes simplemente

 git rebase --onto origin/foo $commit foo 
67
03 нояб. La respuesta es dada Aristóteles Pagaltzis 03 Nov. 2010-11-03 10:08 '10 a las 10:08 2010-11-03 10:08

Yo diría que la sección de recuperación de la reorganización ascendente de la sección de página git -rebase cubre casi todo esto.

border=0

Esto no es diferente de restaurar tu propia permutación: mueves una rama y vuelves a compilar todas las ramas que tenían en su historial a una nueva posición.

11
03 нояб. La respuesta se da Jefromi 03 nov. 2010-11-03 18:39 '10 a las 18:39 2010-11-03 18:39

A partir de git 1.9 / 2.0 Q1 2014, no tendrá que marcar el origen de su rama anterior antes de volver a cargarlo en la rama reescrita, como se describe en la respuesta de Aristotle Pagaltzis :
Vea commit 07d406b y commit d96855f :

Después de trabajar con la rama de topic creada con git checkout -b topic origin/master , el historial del seguimiento remoto de la rama de origin/master puede haber sido rebobinado y reconstruido, lo que llevó al historial de esta forma:

  o---B1 / ---o---o---B2--o---o---o---B (origin/master) \ B3 \ Derived (topic) 

donde origin/master utiliza origin/master para indicar las confirmaciones B3 , B2 , B1 y ahora apunta a B , y su rama topic se estaba ejecutando sobre ella cuando origin/master estaba en B3 .

Este modo utiliza el origin/master reflog para encontrar B3 como una bifurcación, de modo que el topic se puede reinstalar sobre el origin/master actualizado :

 $ fork_point=$(git merge-base --fork-point origin/master topic) $ git rebase --onto origin/master $fork_point topic 

Es por esto que el comando git merge-base tiene una nueva opción:

 --fork-point:: 

Encuentra el punto en el que la rama (o cualquier historia que lleve a <commit> ) se bifurca desde otra rama (o cualquier enlace) <ref> .
Esta no es solo una búsqueda de un antepasado común de los dos confirmaciones, sino que también tiene en cuenta el reflejo <ref> para ver si la historia que lleva a <commit> se ramifica desde una encarnación anterior de la rama <ref> .


El git pull --rebase " git pull --rebase " calcula el punto de la bifurcación de la rama, que se reinstala usando las entradas de búsqueda de la rama " base " (generalmente la rama de seguimiento remoto) en la que se basó la rama para hacer frente cuando la rama "base" se rebobinó y reconstruido

Por ejemplo, si la historia se veía así:

  • la parte superior actual de la rama " base " está en B , pero una muestra anterior mostró que su punta tenía el valor B3 , y luego B2 , y luego B1 antes de continuar con la corrección actual, y
  • la rama reinstalada en la última "base" se basa en el commit B3 ,

trata de encontrar B3 al ver la salida de " git rev-list --reflog base " (es decir, B , B1 , B2 , B3 ) hasta que encuentra una solución que es el antecesor de la punta actual de " Derived (topic) ".

En el interior, tenemos get_merge_bases_many() , que puede calcular esto usando one-go.
Nos gustaría obtener una base de fusión entre Derived y la fijación de fusión ficticia, que resulta en la fusión de todos los consejos históricos de " base (origin/master) ".
Cuando exista una solución de este tipo, deberíamos obtener un único resultado que coincida exactamente con uno de los registros de " base " de reflog.


Git 2.1 (Q3 2014) agregará esta característica más robusta: vea commit 1e0dacd John Keeping ( johnkeeping )

Manejar correctamente el escenario donde tenemos la siguiente topología:

  C --- D --- E <- dev / B <- master@{1} / o --- B' --- C* --- D* <- master 

donde:

  • B' es la versión fija de B , que no coincide con el parche de B ;
  • C* y D* son parches idénticos a C y D respectivamente, y conflictos de texto si se aplican en el orden incorrecto;
  • E depende del texto en D .

El resultado correcto de git rebase master dev es que B identifica como un punto de bifurcación entre dev y master , por lo que C , D , E son confirmaciones que deben repetirse en master ; pero C y D son idénticos a los parches de C* y D* y, por lo tanto, se pueden descartar, por lo que el resultado final:

 o --- B' --- C* --- D* --- E <- dev 

Si la bifurcación no está identificada, la selección de B en una rama que contiene B' conduce a un conflicto, y si los parches idénticos no están definidos correctamente, la selección de C en una rama que contiene D (o, de manera equivalente, D* ) conduce a un conflicto.

8
06 дек. La respuesta está dada por VonC 06 dec. 2013-12-06 14:43 '13 a las 14:43 2013-12-06 14:43