«por favor rebase encima de master y fusionaremos su pull request».
«¿ Puedes por favor aplastar tus commits juntos para que tengamos una githistoria limpia y reversible?”.
«¿ puedes reescribir el mensaje de tu commit para describir mejor el problema que resuelve y cómo lo resuelve?”.
preguntas como estas se hacen comúnmente en las solicitudes de extracción. Veamos por qué existen, cómo realizarlos y sus posibles problemas.,
reescribir el último mensaje de confirmación
Una de las reescrituras de historial más simples que podemos hacer con git es cambiar el mensaje de lastcommit. Digamos que justo después de hacer un commit encuentras un error tipográfico en itsdescription, o encuentras una mejor manera de describir el conjunto de cambios. Para hacer la corrección se ejecuta:
git commit --amend
se abrirá un editor con el último mensaje de confirmación, para que pueda modificarlo. Después de guardar, se creará un nuevo commit con los mismos cambios y el nuevo mensaje, reemplazando el commit con el mensaje anterior.,
esto puede ser útil para incluir archivos que olvidó rastrear, O incluir modificaciones a los archivos que acaba de comprometer. Para hacerlo, puede agregar los cambios y luego realizar la modificación:
git add README.md config/routes.rb git rm notes.txt git commit --amend
Además de editar el mensaje de confirmación, la nueva confirmación contendrá los cambios especificados con git add
y git rm
. También puede editar el autor. Por ejemplo:
git commit --amend --author="Tute Costa and Dan Croak <[email protected]>"
Logro Desbloqueado!, Ahora puede cambiar la última confirmación de su repositorio para incluir cambios más recientes en los archivos, y/o para mejorar el mensaje commit. Pero no empieces a enmendar todas las cosas antes de entender la última sección de esta publicación de blog titulada «peligro».
reescribir otros mensajes de confirmación
nos encantaría hablar de esto ahora, pero necesitamos entender una herramienta más general antes. Estad atentos! Todo lo demás será más fácil una vez que leamos sobre Interactive
Interactive Rebase
git rebase
vuelve a aplicar commits, uno por uno, en orden, desde su rama actual a otra., Acepta varias opciones y parámetros, por lo que es una explicación de la punta del iceberg, suficiente para tender un puente entre los comentarios de StackOverflow o GitHub y las páginas man de git.
una opción interesante que acepta es --interactive
(-i
para abreviar), que abrirá un editor con una lista de las confirmaciones que están a punto de ser cambiadas. Thislist acepta comandos, permitiendo al usuario editar la lista antes de iniciar la acción therebase.
veamos un ejemplo.,
reescribe otros mensajes de confirmación, toma 2
digamos que quiero reescribir cualquiera de las últimas 4 confirmaciones de este blog. Luego Corrogit rebase -i HEAD~4
, y esto es lo que veo:
pick 07c5abd Introduce OpenPGP and teach basic usage pick de9b1eb Fix PostChecker::Post#urls pick 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend # Rebase 8db7e8b..fa20af3 onto 8db7e8b # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
vemos las cuatro últimas confirmaciones, de más antiguas a más nuevas. Ver el comentario debajo de la lista de confirmaciones? Buen trabajo explicando, git! pick
(p
para abreviar) es el defaultaction. En este caso, volvería a aplicar el commit tal cual, sin cambios en su contenido o mensaje. Guardar (y ejecutar) este archivo no haría cambios en el repositorio.,
Si digo reword
(r
para abreviar) en un commit quiero editar:
pick 07c5abd Introduce OpenPGP and teach basic usage pick de9b1eb Fix PostChecker::Post#urls r 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend
Cuando me guarde y cierre el editor, git siga las describe los comandos, landingmyself en el editor de nuevo, como si me hubiera modificado commit 3e7ee36
. Edito thatcommit mensaje, Guardar y salir del editor, y aquí está la salida:
ahora Caleb dice en su mensaje de confirmación «detener todo el resaltado», si usted es un niño o no.
Logro Desbloqueado! Ahora puede cambiar el mensaje de anycommit que desee., Puede hacerlo, solo asegúrese de comprender la sección «peligro».
Squash commits together
otros dos comandos que rebase interactive nos ofrece son:
-
squash
(s
para abreviar), que combina el commit con el anterior (el de la línea anterior) -
fixup
(f
para abreviar), que actúa como «squash», pero descarta el mensaje de esta confirmación
continuaremos trabajando en el ejemplo de rebase que trabajamos antes., Tuvimos cuatro commits, el mío para esta entrada de blog, y otros tres de Caleb, que estaban relacionados con su publicación anterior en PGP:
pick 07c5abd Introduce OpenPGP and teach basic usage pick de9b1eb Fix PostChecker::Post#urls pick 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend
digamos que quiero fusionar los commits de Caleb juntos, porque pertenecen al mismo conjunto de cambios lógicos, y así podemos git revert
encuentra que weprefer no tiene esos cambios en este repositorio. Queremos mantener el primer mensaje de confirmación,y aplastar las dos confirmaciones posteriores en el anterior., Cambio pick
a squash
cuando sea apropiado:
pick 07c5abd Introduce OpenPGP and teach basic usage s de9b1eb Fix PostChecker::Post#urls s 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend
Save, y aterrizo en el editor para decidir el mensaje de confirmación de los meldedthree commits (vea cómo se concatenan uno tras otro):
# This is a combination of 3 commits. # The first commit's message is: Introduce OpenPGP and teach basic usage Besides demystifying a relatively complex tool, protocol, and etiquette, this post is intended to help with problems such as the one outlined in this tweet: > Emailed sensitive info to someone with PGP. They replied, with my > original email, all in clear text. They didn't realize it. # This is the 2nd commit message: Fix PostChecker::Post#urls # This is the 3rd commit message: Hey kids, stop all the highlighting # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Caleb Hearth # Date: Tue Sep 2 09:39:07 2014 -0500 # # rebase in progress; onto 71d4789 # You are currently editing a commit while rebasing branch 'tc-git-rebase' on '71d4789'.
decido eliminar el tercer mensaje de confirmación y añadir una nota más relevante al segundo mensaje de confirmación. Guarde el editor, y las cuatro confirmaciones se transformaron en dos: la de Caleb, y la mía después. ¡Bien!,
podríamos haber usado el comando fixup
, si hubiéramos visto antes que queremos los cambios, pero no el mensaje de confirmación, de la tercera confirmación. En ese caso, los comandos se habrían visto como:
pick 07c5abd Introduce OpenPGP and teach basic usage s de9b1eb Fix PostChecker::Post#urls f 3e7ee36 Hey kids, stop all the highlighting pick fa20af3 git interactive rebase, squash, amend
Cuando se guardaron, el editor habría incluido el tercer mensaje de confirmación ya comentado para nosotros:
Save, y las salidas:
El resultado es el mismo: 2 confirmaciones en lugar de 4, cada una con una única entrada de blog diferente.
Logro Desbloqueado! Ahora puedes fusionar confirmaciones. Siempre, tenga en cuenta la sección de peligro.,
Rebase encima de master
bifurcamos una biblioteca de código abierto, comenzamos a trabajar en una rama de características, y master en el proyecto upstream avanza. Nuestro historial se ve como:
A---B---C feature / D---E---F---G upstream/master
el mantenedor de la biblioteca pide» rebase encima del maestro», por lo que arreglamos cualquier conflicto de fusión que pueda surgir entre ambas ramas, y mantenemos nuestro conjunto de cambios juntos.Al mantenedor le gustaría ver un historial como:
A'--B'--C' feature / D---E---F---G upstream/master
queremos volver a aplicar nuestros commits, uno por uno, en orden, en el maestro del desarrollador principal.,Suena como la descripción del comando rebase! Vamos a ver qué comandos nos llevarían al escenario deseado:
# Point our `upstream` remote to the original fork git remote add upstream https://github.com/thoughtbot/factory_girl.git # Fetch latest commits from `upstream` (the original fork) git fetch upstream # Checkout our feature branch git checkout feature # Reapply it onto upstream's master git rebase upstream/master # Fix conflicts, then `git rebase --continue`, repeat until done # Push to our fork git push --force origin feature
logro desbloqueado! Su rama característica se aplicará sobre el último maestro de la bifurcación original.
Y así llegamos a…
PELIGRO: Se están reescribiendo la historia
el --force
en el último git push
comando? Eso significa que estamos sobrescribiendo la historia de repository., Esto siempre es SEGURO para hacer en commits que no compartimos con otros miembros del equipo, o en ramas que nos pertenecen (ver mis iniciales en el ejemplo de este post del blog).
pero si Fuerzas las ediciones push que ya se compartieron con el equipo (commits que existen fuera de mi repositorio, como los cambios que hice en los commits PGP que ya se han compartido), entonces la rama de todos se sale de sincronización.
reescribir el historial significa abandonar las confirmaciones existentes y crear otras nuevas, que pueden ser muy similares pero diferentes., Si otros basan su trabajo en sus commits anteriores, y luego reescribe y fuerza-empuja sus commits, los miembros de su equipo tendrán que volver a fusionar su trabajo (si notan la pérdida potencial).
en thoughtbot anteponemos nuestras ramas con nuestras iniciales, lo que indica que esos compromisos pueden reescribirse y que otros no deben agregar confirmaciones a la rama. Cuando los commits llegan a master o a una rama compartida, nunca los reescribimos de nuevo.
así que reescribe el historial de git, siempre que las confirmaciones reescritas solo existan en tu repositorio, o tú y tu equipo sabéis que nadie más debería basar su trabajo fuera de ellos.,
Logro Desbloqueado! Ahora sabes cómo rebase siendo un buen ciudadano.