He notado que los dos bloques de los siguientes comandos git tienen comportamientos diferentes y no entiendo por qué.
Tengo una A
y una B
rama que divergen con unacommit
---COMMIT--- (A)
\
--- (B)
Quiero cambiar la B
rama en la última A
(y tener el compromiso en la B
rama)
---COMMIT--- (A)
\
--- (B)
No hay problema si lo hago:
checkout B
rebase A
Pero si lo hago:
checkout B
rebase --onto B A
No funciona en absoluto, no pasa nada. No entiendo por qué los dos comportamientos son diferentes.
Phpstorm git client usa la segunda sintaxis, y me parece completamente rota, por eso pido este problema de sintaxis.
git
git-rebase
Xmanoux
fuente
fuente
Respuestas:
tl; dr
La sintaxis correcta para rebase
B
además deA
usargit rebase --onto
en su caso es:o rebase
B
encima deA
comenzar desde el commit que es el padre deB
referencia conB^
oB~1
.Si estás interesado en la diferencia entre
git rebase <branch>
ygit rebase --onto <branch>
sigue leyendo.El rápido: git rebase
git rebase <branch>
va a rebasar la rama que actualmente ha desprotegido, al que hace referenciaHEAD
, en la parte superior de la última cometen es accesible desde<branch>
pero no deHEAD
.Este es el caso más común de rebase y podría decirse que requiere menos planificación por adelantado.
En este ejemplo,
F
yG
son confirmaciones a las que se puede accederbranch
pero no desdeHEAD
. Decirgit rebase branch
que tomaráD
, esa es la primera confirmación después del punto de bifurcación, y volver a crearla (es decir, cambiar su padre ) encima de la última confirmación accesible desde,branch
pero no desdeHEAD
, es decirG
.The Precise: git rebase --onto con 2 argumentos
git rebase --onto
le permite volver a crear una base a partir de una confirmación específica . Le otorga un control exacto sobre lo que se está rebajando y dónde. Esto es para escenarios en los que necesita ser preciso.Por ejemplo, imaginemos que necesitamos un rebase
HEAD
precisamente alF
inicioE
. Solo estamos interesados en incorporarF
a nuestra rama de trabajo mientras que, al mismo tiempo, no queremos conservarlaD
porque contiene algunos cambios incompatibles.En este caso, diríamos
git rebase --onto F D
. Esto significa:En otras palabras, cambie el padre de
E
deD
aF
. La sintaxis degit rebase --onto
es entoncesgit rebase --onto <newparent> <oldparent>
.Otro escenario en el que esto es útil es cuando desea eliminar rápidamente algunas confirmaciones de la rama actual sin tener que hacer un rebase interactivo :
En este ejemplo, para eliminar
C
yE
de la secuencia usted diríagit rebase --onto B E
, o volveríaHEAD
a poner encima deB
donde estaba el padre anteriorE
.El cirujano: git rebase --onto con 3 argumentos
git rebase --onto
puede ir un paso más allá en términos de precisión. De hecho, le permite volver a crear una base arbitraria de confirmaciones encima de otra.Aquí hay un ejemplo:
En este caso, queremos cambiar el rango exacto
E---H
encimaF
, ignorando a dóndeHEAD
apunta actualmente. Podemos hacerlo diciendogit rebase --onto F D H
, lo que significa:La sintaxis de
git rebase --onto
con un rango de confirmaciones se convierte engit rebase --onto <newparent> <oldparent> <until>
. El truco aquí es recordar que la confirmación a la que hace referencia<until>
se incluye en el rango y se convertirá en la nueva unaHEAD
vez que se complete el rebase.fuente
<oldparent>
nombre se desglosa si las dos partes del rango están en ramas diferentes. Generalmente es: "Incluya todas las confirmaciones a las que se pueda acceder,<until>
pero excluya todas las confirmaciones a las que se pueda acceder<oldparent>
".git rebase --onto <newparent> <oldparent>
es la mejor explicación del comportamiento de Toronto que he visto.--onto
opción, ¡pero esto lo hizo muy claro! Ni siquiera lo entiendo como no podría haberlo entendido antes: D Gracias por el excelente "tutorial" :-)Esto es todo lo que necesita saber para comprender
--onto
:Estás cambiando un padre en un commit, pero no estás proporcionando el sha del commit, solo el sha de su padre actual (antiguo).
fuente
En breve, dado:
Que es lo mismo que (porque
--onto
toma un argumento):Significa las confirmaciones de rebase en el rango (D, H] sobre F. Observe que el rango es exclusivo para la izquierda. Es exclusivo porque es más fácil especificar la primera confirmación escribiendo, por ejemplo,
branch
paragit
encontrar la primera confirmación divergente,branch
es decir, aD
cuál conduceH
.Caso de OP
Se puede cambiar a un solo comando:
Lo que parece un error aquí es la ubicación de lo
B
que significa "mover algunas confirmaciones que conducen a la ramificaciónB
en la parte superior deB
". La pregunta es qué son "algunos commits". Si agrega una-i
bandera, verá que es una confirmación única señalada porHEAD
. La confirmación se omite porque ya está aplicada al--onto
objetivoB
y, por lo tanto, no sucede nada.El comando no tiene sentido en ningún caso donde el nombre de la rama se repite así. Esto se debe a que el rango de confirmaciones serán algunas confirmaciones que ya están en esa rama y durante el rebase se omitirán todas.
Explicación adicional y uso aplicable de
git rebase <upstream> <branch> --onto <newbase>
.git rebase
valores predeterminadosSe expande a:
Pago automático después de rebase.
Cuando se usa de manera estándar, como:
No notará que después de que rebase se
git
muevabranch
a la confirmación de rebase más reciente y lo hagagit checkout branch
(vea elgit reflog
historial). Lo que es interesante cuando el segundo argumento es commit hash cambio, el rebase del nombre de la rama todavía funciona, pero no hay una rama para mover, por lo que terminas en "HEAD separada" en lugar de ser extraído de la rama movida.Omitir confirmaciones divergentes primarias.
El
master
en--onto
se toma desde el 1 degit rebase
argumento.Entonces, prácticamente puede ser cualquier otro commit o rama. De esta manera, puede limitar el número de confirmaciones de rebase al tomar las últimas y dejar las confirmaciones divergentes principales.
Se rebase única confirmación en punta por
HEAD
amaster
y terminan en "cabeza separada".Evite los pagos explícitos.
El valor predeterminado
HEAD
o elcurrent_branch
argumento se toma contextualmente del lugar en el que se encuentra. Es por eso que la mayoría de las personas pagan para bifurcar, lo que quieren volver a redactar. Pero cuando el segundo argumento de rebase se da explícitamente, no tiene que pagar antes de rebase para pasarlo de manera implícita.Esto significa que puede volver a crear commits y ramas desde cualquier lugar. Entonces, junto con el pago automático después del rebase. no tiene que pagar por separado la rama rebaseada antes o después de la rebase
fuente
En pocas palabras,
git rebase --onto
selecciona un rango de confirmaciones y las reajusta en la confirmación dada como parámetro.Lea las páginas del manual
git rebase
, busque "en". Los ejemplos son muy buenos:En este caso le dice a git rebase las confirmaciones de
topicA
quetopicB
en la parte superior demaster
.fuente
Para comprender mejor la diferencia entre
git rebase
ygit rebase --onto
es bueno saber cuáles son los posibles comportamientos para ambos comandos.git rebase
permítanos mover nuestros commits encima de la rama seleccionada. Como aquí:y el resultado es:
git rebase --onto
Es más precisa. Nos permite elegir un compromiso específico donde queremos comenzar y también dónde queremos terminar. Como aquí:y el resultado es:
Para obtener más detalles, le recomiendo que consulte mi propio artículo sobre git rebase - descripción general de Toronto
fuente
git rebase --onto F D
como hijo secundario del padre de D como F , ¿no?Para
onto
usted necesita dos ramas adicionales. Con ese comando, puede aplicar confirmacionesbranchB
que se basan enbranchA
otra rama, por ejemplomaster
. En el ejemplo a continuaciónbranchB
se basabranchA
y desea aplicar los cambios debranchB
onmaster
sin aplicar los cambios debranchA
.mediante el uso de los comandos:
obtendrá la siguiente jerarquía de confirmación.
fuente
rebase --onto branchA branchB
¿eso pondría toda la rama maestra en la cabecera de la rama A?checkout branchB: rebase --onto master branchA
?Hay otro caso en el que
git rebase --onto
es difícil de entender: cuando rebase en una confirmación resultante de un selector de diferencia simétrica (los tres puntos '...
')Git 2.24 (Q4 2019) hace un mejor trabajo al administrar ese caso:
Ver commit 414d924 , commit 4effc5b , commit c0efb4c , commit 2b318aa (27 de agosto de 2019) y commit 793ac7e , commit 359eceb (25 de agosto de 2019) por Denton Liu (
Denton-L
) .Ayudado por: Eric Sunshine (
sunshineco
) , Junio C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) y Johannes Schindelin (dscho
) .Ver commit 6330209 , commit c9efc21 (27 de agosto de 2019) y commit 4336d36 (25 de agosto de 2019) por Ævar Arnfjörð Bjarmason (
avar
).Ayudado por: Eric Sunshine (
sunshineco
) , Junio C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) y Johannes Schindelin (dscho
) .(Fusionada por Junio C Hamano -
gitster
- en commit 640f9cd , 30 sep 2019)En este punto, lea " ¿Cuáles son las diferencias entre doble punto '
..
' y triple punto"...
"en los rangos de compromiso de Git diff? "Aquí: "
master...
" se refiere amaster...HEAD
, que esB
: HEAD es un HEAD lateral (actualmente desprotegido): está haciendo un rebase enB
.¿Qué estás rebaseando? Cualquier commit que no esté en master, y accesible desde la
side
rama: solo hay un commit que se ajusta a esa descripción:D
... que ya está encima deB
!Una vez más, antes de Git 2.24, tal
rebase --onto
resultadoD
resultaría siempre rebajado, pase lo que pase.Eso es similar a la
rebase --onto B A
del OP, que no hizo nada.y el comando fallido era
A
rebase --onto C F topic
significa cualquier commit posteriorF
, accesible portopic
HEAD: eso esG
solo, no enF
sí mismo.El avance rápido en este caso incluiría
F
en la rama rebaseada, lo cual está mal.fuente