2012-07-19 21 views
28

Recientemente comencé a usar git rebase y no estoy 100% seguro de que lo estoy haciendo bien. Por el bien de la pregunta, hay dos ramas en origen, master y next, que se ramificaron desde master.Principios básicos de git rebase

Desde la última sincronización entre los dos, master tenía 2 confirmaciones y next 6:

$ git log --oneline origin/next..origin/master 
59b5552 master commit #2 
485a811 master commit #1 

$ git log --oneline origin/master..origin/next 
4ebf401 next commit #6 
e9b6586 next commit #5 
197ada0 next commit #4 
4a2c3c6 next commit #3 
040a055 next commit #2 
84537bf next commit #1 

Cuando pago y envío next y ejecutar git rebase -i origin/master, me sale el siguiente:

$ git status 
# On branch next 
# Your branch and 'origin/next' have diverged, 
# and have 8 and 6 different commits each, respectively. 

Y, finalmente, después de hacer git pull --rebase, los dos commits de master están en next:

$ git log --oneline origin/next..next 
8741d09 master commit #2 
485a811 master commit #1 

Preguntas:

  1. es el enfoque correcto?
  2. ¿Por qué hay 8 and 6 commits diferentes hasta que se ejecute pull --rebase?
  3. ¿Es posible simplificar el flujo?

muy agradecido :)

+1

Hola David, quiso decir 'git pull --rebase' en lugar de' git rebase --pull'? – MikeSep

+0

@MikeSep eres correcto, arreglado, gracias. –

Respuesta

39

Vamos a empezar desde el principio. Aquí está un diagrama de su estado original:

 
A-B-C (master, origin/master) 
\ 
    D-E-F-G-H-I (next, origin/next) 

Cuando se desprotegió y next porcentualizada next en origin/master, creó 6 nuevas confirmaciones después de los dos que ya están en origin/master. Estos nuevos commits tienen "master commit # 2" (C en mi diagrama) como su ancestro, no su ancestro original donde origin/master y origin/next divergieron (A en mi diagrama), por lo que sus hashes serán diferentes. Creo que esta es la razón por la que verá que next tiene 8 confirmaciones diferentes desde origin/next: las 2 de origin/master y las 6 confirmaciones "repetidas" que estaban en origin/next.

Después git checkout next ; git rebase -i origin/master, usted debe tener presente:

 
A-B-C (master, origin/master) 
\ \ 
    \ D'-E'-F'-G'-H'-I' (next) 
    \ 
    D-E-F-G-H-I (origin/next) 

Se puede ver que next tiene 8 se compromete a que no están en origin/next y origin/next sí tiene 6 se compromete a que no están en next. De acuerdo, esto es solo de acuerdo con los algoritmos SHA-1 de los commits. El contenido real debe coincidir muy de cerca si git diff origin/next next - la diferencia debe mostrar los cambios de B y C (como se indica en el diagrama).

Al hacer git pull --rebase mientras que todavía en next, se va a buscar cambios de la fuente (el control remoto origin/next) y rebasa la rama actual (next) en que remoto. Esto provoca que los cambios que estaban en el next pero no en origin/next aparezcan después de origin/next en la nueva rama next.Debería verse así:

 
A-B-C (master, origin/master) 
\ 
    D-E-F-G-H-I (origin/next) 
      \ 
       B'-C' (next) 

Si esto es lo que quería que fuera el gráfico del historial, ha tenido éxito.

Sin embargo, sospecho que realmente quería que las cosas se vean como el diagrama central, especialmente si next es una rama de características donde está trabajando en la siguiente parte del proyecto y master es para código estable y correcciones de errores pequeños. Si es así, entonces debería haber hecho git push en lugar de git pull --rebase para que el control remoto refleje su versión del historial en lugar de hacerlo al revés.

+0

Supongo que 'git rebase --pull' es muy parecido a' git pull --rebase'.Hace una búsqueda y luego un 'git rebase @ {u}' Bueno, eso es una mentira, pero es una manera fácil de pensar sobre eso. Pero el punto es que su sucursal local se restablece a @ {u} y luego todas las confirmaciones locales en su antigua bifurcación antes del reinicio se reproducen en la parte superior de lo que tiene la corriente ascendente. Esto permite un empuje rápido hacia abajo trivial. –

+0

Suponiendo que 'git rebase --pull' era un error tipográfico y debería haber sido' git pull --rebase', entonces creo que se volvería a ordenar 'next' en' D'-E'-F'-G'-H'- I'-B'-C''. Suena bien? Si es así, voy a editar mi respuesta en consecuencia. – MikeSep

+1

Después de 'git pull --rebase' obtendrás A-D-E-F-G-H-I-B'-C '. El g-p-r siempre forzará a su sucursal local (siguiente) a contener todas las confirmaciones en @ {u} (origen/siguiente) y luego todo lo que sea único para el próximo se reproducirá (probablemente seleccionado) en la parte superior. Felicite a git por ser lo suficientemente inteligente como para no intentar crear D "-E" -F "-G" -H "-I" –

0

Comience con los pasos muy simples para cambiar el rumbo de su bifurcación con el maestro; Nombre;

git-rebase 

Sinopsis;

git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] 
     [<upstream>] [<branch>] 
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] 
     --root [<branch>] 
git rebase --continue | --skip | --abort | --edit-todo 

Descripción; Supongamos que existe la siguiente historia y la rama actual es "muestra":

A---B---C sample 
     /
    D---E---F---G master 

A partir de este punto, el resultado de cualquiera de los siguientes comandos:

git rebase master 
git rebase master sample 

sería:

A'--B'--C' sample 
       /
    D---E---F---G master 

NOTA: El último formulario es solo una abreviatura de git checkout sample seguido de git rebase master. Cuando la base de datos salga de la muestra seguirá siendo la sucursal retirada.

Si la rama ascendente ya contiene un cambio que ha realizado (por ejemplo, porque envió por correo un parche que se aplicó en sentido ascendente), se saltará ese compromiso. Por ejemplo, correr 'git rebase master' en la siguiente historia (en la que A' y A introducir el mismo conjunto de cambios, pero tienen diferente información confirmador):

A---B---C sample 
     /
    D---E---A'---F master 

se traducirá en:

B'---C' sample 
      /
D---E---A'---F master 

Todos estos fueron los conocimientos diagramaticos del proceso de rebase. Una vez que resuelva los conflictos que se encuentran después de escribir git rebase master resuelva los conflictos y escriba git add -u para agregar los códigos modificados al repositorio. después de eso, realice el comando git rebase --continue y continúe resolviendo los conflictos y repitiendo el comando; se encontró

git add -u 

y

git rebase --continue 

hasta que no haya conflictos. Por fin el comando final será,

git push --force origin sample(your branch name) 
+0

para consulta externa, siga https://www.kernel.org/pub/software/scm/git/docs/git-rebase.html –