jose r
En Git puedo usar una reorganización interactiva para reescribir el historial, esto es genial porque en mi rama de características hice un montón de confirmaciones con código que funcionaba parcialmente mientras exploraba diferentes refactores y formas de hacerlo.
Me gustaría juntar muchos de los compromisos antes de reorganizar o fusionar la rama en el maestro.
Algunas confirmaciones inventadas en orden de primero (arriba) a abajo (último)
1. Initial commit on feature branch "Automatic coffee maker UI"
2. Add hot chocolate as product
3. Add tea as product. Products are now generic
4. Create in memory data store for adapter tests
5. Cry because I can't get entity framework to create a composite key. Integration tests broken.
6. Implemented composite key!!
7. All tests green and feature done!
Digamos que quiero mantener las confirmaciones 3, 4 y 7.
Usando rebase quiero “aplastar” confirmaciones
- 1 y 2 entran en 3.
- 4 estancias
- 5 y 6 entran en 7
Idealmente en el rebase interactivo que haría
1. squash
2. squash
3. pick (contains the work of 1 & 2)
4. pick
5. squash
6. squash
7. pick (contains the work of 5 & 6)
Pero eso es al revés porque squash fusiona una confirmación con su confirmación anterior. No puedo entender cómo hacer que se aplaste hacia adelante.
¿Estoy siendo difícil y debo aceptar que no funcionará (prefiero que funcione) o hay alguna forma de lograrlo?
Estoy invocando este comando con
git checkout My-feature-branch
git rebase master -i
Luego estoy editando la lista de confirmaciones que aparecen e intento terminarla guardando el archivo y editando el editor, lo que normalmente funciona para mí.
También debe reordenar las confirmaciones para que la confirmación que se debe mantener se presente antes que las confirmaciones para aplastar si esto es factible.
Si esto no es factible, porque entonces surgirían conflictos que no desea resolver, simplemente hágalo.
1. pick
2. squash
3. squash
4. pick
5. pick
6. squash
7. squash
Cuando haya terminado con los ajustes, puede editar el mensaje de confirmación para que contenga el mensaje que desea que tengan las confirmaciones finales. Muy fácil. 🙂
Incluso podrías ser capaz de hacer
1. pick
2. fixup
3. squash
4. pick
5. pick
6. fixup
7. squash
Entonces creo que solo debería haber una vez que se inicie el editor de mensajes de confirmación, ya que con la corrección, el mensaje de confirmación anterior simplemente se toma sin iniciar el editor.
En Squash, cuando se activa el editor de mensajes de confirmación, también recibe ambos mensajes de confirmación, el de la confirmación que se va a aplastar y el de la confirmación que se va a aplastar, por lo que simplemente puede eliminar el mensaje de confirmación que no desea. mantener.
-
pero luego mantiene la fecha de la primera confirmación. ¿Cómo hago para que use la fecha de la última confirmación?
–Michael Hewson
12 de noviembre de 2019 a las 18:18
-
@MichaelHewson Supongo que no hay una manera fácil; Cambiaré manualmente la fecha.
– luizfls
12 abr 2021 a las 19:34
tera
De hecho, es posible aplastar un compromiso en el siguiente confirme durante la reorganización interactiva y conserve por completo la identidad de la segunda de esas confirmaciones (incluido el autor, la fecha, etc.).
Sin embargo, el método es algo complicado, por lo que el soporte nativo de git rebase -i
todavía sería apreciado sin embargo.
Lo demostraré con solo tres confirmaciones aaaaaaa A
, bbbbbbb B
y ccccccc C
donde queremos doblar A
en B
y preservar B
Identidad de: (El método se generaliza fácilmente a más confirmaciones)
git rebase -i aaaaaaa^
- Modifique el script de edición para que se detenga después de confirmar
B
y sal del editor:pick aaaaaaa A edit bbbbbbb B pick ccccccc C
- Cuando rebase se ha detenido después de
B
revertir la última confirmación dos vecesluego continúa:git revert HEAD git revert HEAD git rebase --continue
Debido a que revertir la reversión restaura el estado anterior, todas las confirmaciones siguientes se aplicarán limpiamente. La secuencia de
B
yRevert "B"
juntos no tiene ningún efecto, pero el primero de esos compromisos lleva la identidad completa del compromiso B (de hecho, en esta etapa todavía es comprometerseB
).
B
yRevert "B"
podrían ser aplastados juntos para formar un compromiso no operativo que lleva la identidad del compromiso B adelante con un compromiso separadorebase -i --keep-empty aaaaaaa^
. Esto es muy útil y recomendado para evitar conflictos de combinación falsos, especialmente en casos más complejos. Sin embargo, omitiremos ese paso aquí y solo mantendremos las confirmaciones juntas.
El compromiso importante ahora esRevert "Revert "B""
que llevará todos los cambios realizados originalmente porB
. - Ahora
rebase -i aaaaaaa^
otra vez para moverA
pasado ambosB
yRevert "B"
mientras aplastaB
en ambosRevert "B"
yA
:pick bbbbbbb B squash b111111 Revert "B" squash a222222 A squash b333333 Revert "Revert "B"" pick c444444 C
porque la secuencia de
B
yRevert "B"
no tiene ningún efecto, puede mover cualquier compromiso más allá de él mientras crea solo conflictos de fusión que se pueden resolver de manera trivial. - Cuando rebase se detiene con un conflicto de fusión, use
git mergetool
con una herramienta que puede resolver automáticamente conflictos triviales y dejar que las herramientas hagan precisamente eso. - Rebase se detendrá nuevamente para permitirle editar el mensaje de confirmación de la confirmación aplastada. Edita a tu gusto.
git rebase --continue
y listo
-
Esta debería ser la respuesta. Resuelve la pregunta correctamente.
– Diogo
22 de mayo de 2021 a las 4:59
-
Estoy de acuerdo, aunque mi opinión puede estar sesgada. No estoy seguro de si podemos convencer a @JoshR de que se moleste después de cuatro años, pero me alegro de que mi respuesta te haya resultado útil.
– tera
23 de mayo de 2021 a las 10:07
La respuesta de Vampire es correcta, pero quiero ofrecer una perspectiva diferente. Creo que aquí es donde te estás poniendo más nervioso de lo necesario: empiezas con:
Digamos que quiero mantener las confirmaciones 3, 4 y 7.
pero luego agrega:
- 1 y 2 entran en 3.
- 4 estancias
- 5 y 6 entran en 7
Pero esto significa que desea conservar (el contenido de) todos de 1, 2, 3, 4, 5, 6 y 7… pero no como confirmaciones separadas. El rebase interactivo squash
no significa “tirar”, ni siquiera “tirar el mensaje de confirmación”, simplemente significa “combinar”. Sería mejor si el verbo fuera “combinar” o “fundir” o “mezclar” o algo así. Entonces la secuencia (pick, squash, squash) significa: mantenga los tres, mientras los aplica en ese orden, luego haga un gran compromiso con ellos.
Como ya se señaló, una vez que Git va a hacer un gran compromiso con ellos, Git le da otra oportunidad de editar los tres mensajes de compromiso combinados en un gran mensaje de compromiso.
Cuando se hace la rebase, no has guardado ninguna de las confirmaciones originales. En cambio, has hecho nuevo se compromete No importa con precisión cómo se armó su nuevo primer compromiso a partir de partes, solo cuál fue la fuente final y qué puso en el gran mensaje de compromiso.
-
Llámame quisquilloso, pero si bien es totalmente correcto, esto no responde la pregunta OP, sino que solo le dice que usó una redacción incorrecta, ¿no es así? Si es así, debería ser un comentario a la pregunta, no una respuesta.
– Vampiro
29 mayo 2017 a las 16:52
-
@Vampire: sí, probablemente debería ser un comentario. Sin embargo, los límites de los comentarios (espacio y formato) hacen que no encaje muy bien. Y, no es necesariamente sólo fraseología: la idea de que la confirmación cambia de ID y, por lo tanto, no es la confirmación original en absoluto, es importante, ya que otras ramas pueden conservar la confirmación original por su ID original.
– torek
29 de mayo de 2017 a las 18:07
-
@JoshR si hubiera eliminado las confirmaciones, también habría descartado los cambios que realizó dentro de ellos.
– Vampiro
31 de mayo de 2017 a las 9:31
-
Correcto: no quieres soltar ellos, desea resumirlos en un nuevo compromiso 1a que es igual a 1 + 2 + 3 en términos de cambios de fuente (ensamblados por tres
git cherry-pick -n
operaciones).– torek
1 jun 2017 a las 21:58
-
O squashes o fixups en un rebase interactivo, exactamente lo que quería hacer. Simplemente confundió el orden en el que funcionan las estrofas. Usando
cherry-pick
porque esto podría funcionar, pero sería bastante engorroso si simplemente pudiera hacer una reorganización interactiva.– Vampiro
2 de junio de 2017 a las 1:07
Mi manera preferida de hacer esto es simplemente un reset
suma un commit -C
.
git rebase -i origin/main # or some other commit
Lo que abre su editor, que hago que se vea así:
...
pick aafaa Merge me forward
edit bbfbb Into me
...
Luego, cuando el rebase se detiene en bbfbb
hacer
git reset --soft HEAD^
git commit --amend -C HEAD@{1} # could put an explicit commit here
git rebase --continue
también se puede poner en una sola lista de tareas pendientes de rebase:
...
pick aafaa Squash me forward
pick bbfbb Into me
exec git reset --soft HEAD^ && git commit --amend -C HEAD@{1}
...
Lo que quieres es:
1. pick
2. squash
3. fixup
4. pick
5. squash
6. squash
7. fixup
Luego, cuando aparezcan las nuevas confirmaciones combinadas en el editor, elimine las líneas de las confirmaciones seleccionadas y deje las correcciones. Los parches de funciones resultantes deben tener el mensaje de confirmación de la última confirmación de la serie de esa manera.
No estoy completamente seguro de lo que estás experimentando.
squash
haría exactamente lo que estás buscando; combine 1 y 2 en 3, y 5 y 6 en 7. Lo que quedaría sería (aparentemente) confirmaciones, 3, 4 y 7. ¿Tiene algún problema con estos comandos? Tenga en cuenta que puede probarlos en su repositorio local sin problemas, pero solo si tiene un repositorio remoto puede restablecerlo.– Makoto
26 mayo 2017 a las 22:17
Recibo un mensaje “error: no se puede ‘aplastar’ sin una confirmación previa”, que me lanzó a un bucle y me hace pensar que el n. ° 1 está tratando de squash al n. ° 0, que no existe y no al n. ° 2
– Josh R.
26 mayo 2017 a las 22:31
¿Cómo estás invocando esto? Muéstranos ese comando.
– Makoto
26 mayo 2017 a las 22:33
@Makoto estás equivocado, es al revés, tal como dijo Josh en su pregunta. 😉 Además, debido a que el reflog está allí de forma predeterminada, siempre puede deshacer fácilmente lo que hizo con una rebase sin que haya ningún repositorio remoto presente. 😉
– Vampiro
26 mayo 2017 a las 23:29
Gran pregunta. Necesitaba exactamente esto, ya que reordenar las confirmaciones genera conflictos. La respuesta de @ Vampire es una gran solución que no genera ningún trabajo adicional.
–Filip Kubicz
22 de diciembre de 2021 a las 11:13