strategy how drop commits all git git-rebase

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 es D sobre F

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 hasta H sobre F

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)