git - how - rebase console
No puedo entender el comportamiento de git rebase--onto (5)
tl; dr
La sintaxis correcta para rebase
B
en la parte superior de
A
usando
git rebase --onto
en su caso es:
git checkout B
git rebase --onto A B^
o
vuelva a poner
B
en la parte superior de
A
partir del commit que es el padre de
B
referencia con
B^
o
B~1
.
Si está interesado en la diferencia entre
git rebase <branch>
y
git rebase --onto <branch>
leyendo.
El rápido: git rebase
git rebase <branch>
va a rebase de la rama que ha desprotegido actualmente, referenciada por
HEAD
, encima de la
última confirmación a la que se puede acceder
desde
<branch>
pero
no
desde
HEAD
.
Este es el caso más común de rebase y podría decirse que requiere menos planificación por adelantado.
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
/ /
D---E (HEAD) D---E (HEAD)
En este ejemplo,
F
y
G
son confirmaciones a las que se puede acceder desde la
branch
pero no desde
HEAD
.
Decir
git rebase branch
tomará
D
, que es el primer commit después del punto de ramificación, y lo
rebaase
(es decir,
cambie su padre
) encima del último commit accesible desde
branch
pero no desde
HEAD
, eso es
G
The Precise: git rebase --onto con 2 argumentos
git rebase --onto
permite
git rebase --onto
a crear
una
base a
partir de una confirmación específica
.
Le otorga un control exacto sobre lo que se está rebautizando y dónde.
Esto es para escenarios en los que necesita ser preciso.
Por ejemplo, imaginemos que necesitamos cambiar la base de
HEAD
precisamente sobre
F
partir de
E
Solo estamos interesados en incorporar
F
a nuestra rama de trabajo, mientras que, al mismo tiempo, no queremos conservar
D
porque contiene algunos cambios incompatibles.
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
/ /
D---E---H---I (HEAD) E---H---I (HEAD)
En este caso, diríamos
git rebase --onto FD
.
Esto significa:
Rebase el commit accesible desde
HEAD
cuyo padre esD
sobreF
En otras palabras,
cambie el padre
de
E
de
D
a
F
La sintaxis de
git rebase --onto
es entonces
git 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 :
Before After
A---B---C---E---F (HEAD) A---B---F (HEAD)
En este ejemplo, para eliminar
C
y
E
de la secuencia, diría
git rebase --onto BE
, o rebase
HEAD
en la parte superior de
B
donde el padre anterior era
E
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:
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
/ /
D---E---H---I (HEAD) E---H (HEAD)
En este caso, queremos cambiar el rango exacto
E---H
sobre
F
, ignorando hacia dónde apunta
HEAD
actualmente.
Podemos hacerlo diciendo
git rebase --onto FDH
, que significa:
Rebase el rango de confirmaciones cuyo padre es
D
hastaH
sobreF
La sintaxis de
git rebase --onto
con un
rango de confirmaciones
se convierte en
git rebase --onto <newparent> <oldparent> <until>
.
El truco aquí es recordar que el commit al que hace referencia
<until>
está
incluido
en el rango y se convertirá en el nuevo
HEAD
después de que se complete el rebase.
He notado que los dos bloques de los siguientes comandos git tienen comportamientos diferentes y no entiendo por qué.
Tengo una rama
A
y una
B
que divergen con una
commit
---COMMIT--- (A)
/
--- (B)
Quiero reajustar la rama
B
en la última
A
(y tener el commit en la rama
B
)
---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.
En breve, dado:
Before rebase After rebase
A---B---C---F---G (branch) A---B---C---F---G (branch)
/ / /
D---E---H---I (HEAD) / E''---H'' (HEAD)
/
D---E---H---I
git rebase --onto F D H
Lo cual es lo mismo que (porque
--onto
toma un argumento):
git rebase D H --onto F
Significa las confirmaciones de rebase en el rango (D, H] encima de F. Observe que el rango es exclusivo a la izquierda.
Es exclusivo porque es más fácil especificar la primera confirmación escribiendo, por ejemplo,
branch
para permitir que
git
encuentre la primera confirmación divergente de la
branch
es decir,
D
conduce a
H
Caso de OP
o---o (A)
/
o (B)(HEAD)
git checkout B
git rebase --onto B A
Se puede cambiar a un solo comando:
git rebase --onto B A B
Lo que parece un error aquí es la colocación de
B
que significa "mover algunas confirmaciones que conducen a la rama
B
encima de
B
".
La pregunta es qué son "algunos commits".
Si agrega el indicador
-i
, verá que es una confirmación única señalada por
HEAD
.
El commit se omite porque ya se aplica a
--onto
target
B
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
defecto.
git rebase master
Se expande a:
git rebase --onto master master HEAD
git rebase --onto master master current_branch
Pago automático después de rebase.
Cuando se usa de manera estándar, como:
git checkout branch
git rebase master
No notará que después de rebase
git
mueve la
branch
a la confirmación rebase más reciente y hace
git checkout branch
(vea el historial de
git reflog
).
Lo que es interesante cuando el segundo argumento es
commit hash, en
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 desprotegido en la rama movida.
Omitir confirmaciones divergentes primarias.
El
master
en
--onto
se toma del primer argumento
git rebase
.
git rebase master
/ /
git rebase --onto master master
Entonces, prácticamente puede ser cualquier otro commit o rama. De esta forma, puede limitar el número de confirmaciones de rebase al tomar las últimas y dejar las confirmaciones divergentes principales.
git rebase --onto master HEAD~
git rebase --onto master HEAD~ HEAD # Expanded.
Reescribirá la confirmación única señalada por
HEAD
para
master
y terminará en "HEAD separada".
Evite los pagos explícitos.
El argumento predeterminado
HEAD
o
current_branch
se toma contextualmente del lugar en el que se encuentra. Esta es la razón por la cual la mayoría de las personas hacen checkout para bifurcar, lo que quieren rehacer.
Pero cuando el segundo argumento de rebase se da explícitamente, no tiene que pagar antes de rebase para pasarlo de manera implícita.
(branch) $ git rebase master
(branch) $ git rebase master branch # Expanded.
(branch) $ git rebase master $(git rev-parse --abbrev-ref HEAD) # Kind of what git does.
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.
(master) $ git rebase master branch
(branch) $ # Rebased. Notice checkout.
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 de manual de
git rebase
, busque "
git rebase
".
Los ejemplos son muy buenos:
example of --onto option is to rebase part of a branch. If we have the following situation:
H---I---J topicB
/
E---F---G topicA
/
A---B---C---D master
then the command
git rebase --onto master topicA topicB
would result in:
H''--I''--J'' topicB
/
| E---F---G topicA
|/
A---B---C---D master
En este caso, le dice a git que vuelva a crear las confirmaciones del
topicA
al tema
topicB
en la parte superior del
master
.
Esto es todo lo que necesita saber para comprender:
--onto
:
git rebase --onto <newparent> <oldparent>
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).
Para
onto
usted necesita dos ramas adicionales.
Con ese comando puede aplicar confirmaciones de la
branchB
que se basan en la
branchA
en otra rama, por ejemplo,
master
.
En el ejemplo a continuación,
branchB
se basa en
branchA
y desea aplicar los cambios de
branchB
en
master
sin aplicar los cambios de
branchA
.
o---o (master)
/
o---o---o---o (branchA)
/
o---o (branchB)
mediante el uso de los comandos:
checkout master
rebase --onto branchA branchB
obtendrá la siguiente jerarquía de confirmación.
o''---o'' (branchB)
/
o---o (master)
/
o---o---o---o (branchA)