Me gustaría cambiar la base a un commit específico, no a un HEAD de la otra rama:
A --- B --- C master
\
\-- D topic
a
A --- B --- C master
\
\-- D topic
en vez de
A --- B --- C master
\
\-- D topic
¿Cómo puedo lograr eso?
git
version-control
rebase
git-rebase
Ondra Žižka
fuente
fuente
git checkout B
antes de corrergit rebase
?rebase
comando son lo que importa.Respuestas:
Puede evitar el uso del parámetro --onto haciendo una rama temporal en el commit que desee y luego use rebase en su forma simple:
fuente
git rebase temp
(cuando está en grupo ) se da por vencido con "Los grupos de sucursales actuales están actualizados".git rebase --onto <target> <from> <to>
para poder especificar <from> commit.Incluso puedes tomar un enfoque directo:
fuente
topic
ycommitB
.It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn.
lo intenté de nuevo ahora y parecía funcionar bien.m > n
.Use la opción "sobre":
fuente
D
yD^
sería hash de la última y próxima a la última confirmación de "tema"?git rebase --onto <new-parent> <old-parent>
. Consulte Configuración del puntero padre git a un padre diferente . En su caso, <nueva-parent> es B, y <pasada de padres> es A.git rebase --onto <commit-ID> master
git rebase --onto master <commit-ID-of-old-parent>
y para OPgit rebase --onto B A
.El comentario de jsz anterior me ahorró un montón de dolor, así que aquí hay una receta paso a paso basada en ella que he estado usando para cambiar la base / mover cualquier confirmación encima de cualquier otra confirmación:
git rebase --onto <new parent> <old parent>
En el ejemplo anterior, es tan simple como:
fuente
git rebase --onto B master
, vea mi respuesta para una explicación más completa.Solución de tema
El comando correcto para responder la pregunta publicada podría ser cualquiera de los siguientes (suponiendo que la rama
topic
ya esté desprotegida):Si
topic
no está desprotegido, simplemente agreguetopic
el comando (excepto el último) así:Alternativamente, revise la sucursal primero con:
Rebase cualquier cadena de confirmaciones a una confirmación de destino
La forma básica del comando que necesitamos, basada en la documentación, es:
<Branch>
es opcional y todo lo que hace es verificar la rama especificada antes de ejecutar el resto del comando. Si ya ha desprotegido la rama que desea cambiar, entonces no necesita esto. Tenga en cuenta que debe haber especificado<Upstream>
para especificar<Branch>
o git pensará que está especificando<Upstream>
.<Target>
es la confirmación a la que adjuntaremos nuestra cadena de confirmaciones. Al proporcionar un nombre de sucursal, simplemente está especificando la confirmación principal de esa rama.<Target>
puede ser cualquier confirmación que no se incluirá en la cadena de confirmaciones que se mueven. Por ejemplo:Para mover toda la rama de la característica, no se puede seleccionar
X
,Y
,Z
ofeature
como el<Target>
ya que los todos son commits dentro del grupo que está siendo movido.<Upstream>
es especial porque puede significar dos cosas diferentes. Si se trata de una confirmación que es un antepasado de la rama desprotegida, entonces sirve como punto de corte. En el ejemplo que he proporcionado, esto podría ser cualquier cosa que no esC
,D
omaster
. Todos los commits posteriores<Upstream>
hasta el encabezado de la rama desprotegida son los que se moverán.Sin embargo, si
<Upstream>
no es un ancestro, entonces git realiza una copia de seguridad de la cadena desde el commit especificado hasta que encuentre un ancestro común con la rama desprotegida (y aborta si no puede encontrar uno). En nuestro caso, una<Upstream>
deB
,C
,D
, omaster
se traducirán en cometerB
servir como punto de corte.<Upstream>
es en sí mismo un comando opcional y si no se especifica, entonces git mira al padre de la rama desprotegida que es el equivalente de ingresarmaster
.Ahora que git ha seleccionado las confirmaciones que cortará y moverá, las aplicará para
<Target>
omitir las que ya se hayan aplicado al objetivo.Ejemplos y resultados interesantes
Usando este punto de partida:
git rebase --onto D A feature
Se aplicará compromete
B
,C
,X
,Y
,Z
para cometerD
y terminan saltandoB
yC
debido a que ya se han aplicado.git rebase --onto C X feature
Aplicará commits
Y
yZ
commitC
, eliminando efectivamente commitX
fuente
Una solución más simple es
git rebase <SHA1 of B> topic
. Esto funciona independientemente de dóndeHEAD
esté.Podemos confirmar este comportamiento desde git rebase doc
Quizás esté pensando qué sucederá si también menciono SHA1
topic
en el comando anterior.git rebase <SHA1 of B> <SHA1 of topic>
Esto también funcionará, pero el rebase no hará referencia
Topic
a una nueva rama así creada yHEAD
estará en estado separado. Entonces, desde aquí, debe eliminar manualmente la antiguaTopic
y crear una nueva referencia de rama en la nueva rama creada por rebase.fuente
He usado una mezcla de soluciones descritas anteriormente:
Me resultó mucho más fácil de leer y entender. La solución aceptada me llevó a un conflicto de fusión (demasiado flojo para arreglarlo a mano):
fuente
Dado que el rebase es tan fundamental, aquí hay una expansión de la respuesta de Nestor Milyaev . La combinación de los comentarios de jsz y Simon South de la respuesta de Adam Dymitruk produce este comando que funciona en la
topic
rama independientemente de si se ramifica desde elmaster
commit de la ramaA
oC
:Tenga en cuenta que se requiere el último argumento (de lo contrario, rebobina su rama para confirmar
B
).Ejemplos:
Entonces, el último comando es el que normalmente uso.
fuente
Hay otra forma de hacerlo o si desea volver a más de un solo commit.
Aquí hay un ejemplo para volver a
n
número de confirmaciones:En aras de esta pregunta, esto también se puede hacer:
El comando funciona perfectamente
git version 2.7.4
. No lo he probado en ninguna otra versión.fuente