¿Cómo recupero / Resincroniza después de que alguien empuja un rebase o un reset a una rama publicada?

StackOverflow https://stackoverflow.com/questions/4084868

Pregunta

Todos hemos oído que uno nunca debe publicada rebase el trabajo, que es peligroso, etc. Sin embargo, no he visto ninguna de las recetas publicadas de cómo hacer frente a la situación en caso de un rebase es publicó .

Ahora, tenga en cuenta que esto sólo es realmente factible si el repositorio solamente se clona por un grupo conocido (y preferiblemente pequeña) de las personas, por lo que todo aquel que empuja el rebase o restablecimiento puede notificar a todos los demás que tendrán que prestar atención próxima vez que fetch (!).

Una solución obvia que he visto va a funcionar si no tiene commits locales en foo y se hace porcentualizada:

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

Esto simplemente va a tirar el estado local de foo a favor de su historia como por el repositorio remoto.

Pero, ¿cómo lidiar con la situación si se ha cometido cambios locales sustanciales en esa rama?

¿Fue útil?

Solución

volver a estar en sincronía después de un rebase empujado no es realmente tan complicado 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

Ie. primero se configura un marcador de donde estaba originalmente la rama remota, a continuación, se lo utiliza para reproducir su commits locales a partir de ese punto en adelante en la rama remota porcentualizada.

El reajuste es como la violencia: si no se soluciona el problema, sólo tiene más de ella. ?

Se puede hacer esto sin el marcador por supuesto, si usted busca la origin/foo pre-rebase de comprometerse ID, y el uso que.

Este es también cómo hacer frente a la situación en la que se olvidó de crear un marcador antes ir a buscar. No se pierde nada - sólo tiene que comprobar el reflog para la rama remota:

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

Esto imprimirá el ID que origin/foo señaló antes de la más reciente de obtención de eso cambió su historia confirmación.

A continuación, puede simplemente

git rebase --onto origin/foo $commit foo

Otros consejos

Yo diría que el se recupera de la sección aguas arriba rebase del git- página hombre rebase tapas más o menos todo esto.

Es realmente no es diferente de la recuperación de su propia rebase - mover un brazo, y reajustar todas las ramas que tenían en su historia en su nueva posición

.

A partir de git 1.9 / 2.0 Q1 2014, usted no tendrá que marcar su origen de la rama anterior antes de rebase en la rama ascendente reescrito, como se describe en Aristóteles Pagaltzis 's respuesta :
Ver cometer 07d406b y cometer d96855f :

  

Después de trabajar en la rama topic creada con git checkout -b topic origin/master, la historia de la distancia de seguimiento origin/master rama puede haber sido rebobinada y reconstruido, lo que lleva a una historia de esta forma:

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

donde origin/master utiliza para señalar compromete B3, B2, B1 y ahora apunta a B, y su sucursal topic se inició en la parte superior de nuevo cuando estaba en origin/master B3.

     

Este modo utiliza la reflog de origin/master encontrar B3 como el punto de tenedor, por lo que el topic puede porcentualizada en la parte superior de la actualización origin/master por:

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

Esa es la razón por la href="http://git-scm.com/docs/git-merge-base" rel="nofollow noreferrer"> git merge-base comando tiene una nueva opción:

--fork-point::
  

Encuentre el punto en que una rama (o cualquier historia que conduce a <commit>) en forma de tenedor de otra rama (o cualquier referencia) <ref>.
  Esto no sólo tiene que buscar el ancestro común de los dos confirmaciones, pero también tiene en cuenta la reflog de <ref> para ver si la historia que lleva a <commit> fork de una encarnación anterior de la rama <ref> .


  

El comando "git pull --rebase" calcula el punto de la rama tenedor siendo porcentualizada utilizando las entradas reflog de la rama "base" (por lo general una rama remota de seguimiento) El trabajo de la rama se basa en, con el fin de hacer frente al caso en el el cual la rama "base" se ha rebobinado y reconstruido.

Por ejemplo, si la historia parecía que:

  
      
  • la punta actual de la rama "base" es en B, pero a principios de Fetch observó que su punta solía ser B3 y luego B2 y luego B1   antes de llegar a la corriente cometer, y
  •   
  • la rama que se reajusta en la parte superior de la última "base" se basa en comprometerse B3,
  •   
     

intenta encontrar B3 pasando a través de la salida de "git rev-list --reflog base" (es decir B, B1, B2, B3) hasta que encuentra una confirmación de que es un antepasado de la punta actual "Derived (topic)".

     

A nivel interno, tenemos get_merge_bases_many() que puede calcular esto con una sola vez.
  Nos gustaría una fusión-base entre Derived y una fusión ficticia comprometen que daría como resultado la fusión de todas las puntas históricas de "base (origin/master)".
  Cuando tal cometer existen, debemos obtener un único resultado, que coincide exactamente con una de las entradas de reflog "base".


Git 2.1 (Q3 2014) añade que esta característica esté más robusto para esto: cometer 1e0dacd por John Keeping (johnkeeping)

manejar correctamente la situación en la que nostiene la siguiente topología:

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

donde:

  • B' es una versión fija plano de B que no se patch-idéntica con B;
  • C* y D* son patch-idéntica a C y D respectivamente y el conflicto textualmente si se aplican en el orden equivocado;
  • E depende textualmente en D.

El resultado correcto de git rebase master dev es que B se identifica como el tenedor-punto de dev y master, de modo que C, D, E son los commit esa necesidad para que se reproduzca en master; pero C y D son patch-idéntica con C* y D* y así puede ser bajado, de modo que el resultado final es:

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

Si no se identifica el tenedor de punto, a continuación, recogiendo B a una rama que contiene resultados B' en un conflicto y si los commit patch-idénticas no se identifican correctamente, entonces recoger C a una rama que contiene D (o equivalentemente D*) resulta en un conflicto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top