Etiqueta: git

  • Mi .gitconfig

    Este es el contenido de mi fichero .gitconfig:
    [color]
            ui = auto
    [core]
            pager = less -FMRiX
            excludesfile = /home/<myuser>/.config/git/excludes
    [push]
            default = simple
    [alias]
            hist = log --pretty=format:'%C(yellow)[%ad]%C(reset) %C(green)[%h]%C(reset) | %C(cyan)%s %C(bold red){{%an}}%C(reset) %C(magenta)%d%C(reset)' --graph --date=relative
            head = hist -10 --topo-order
            co = checkout
            wd = diff --color-words --word-diff-regex=[^[:space:],.\\:\\'\\\"\\+\\=\\/]+
            fork = !zsh -c '"orig_helper=${2:+${1}}; orig=${orig_helper:-main}; target=${2:-${1:-HEAD}}; diff -U 1 <(git rev-list --first-parent ${orig}) <(git rev-list --first-parent ${target}) | tail -1"' -
            showfork = !zsh -c 'git show $(git fork ${1} ${2})' -
            difffork = !zsh -c '"target=${2:-${1:-HEAD}}; git diff $(git fork ${1} ${2}) ${target}"' -
    [user]
            email = my@email.com
            name = My name
    [filter "lfs"]
    	clean = git-lfs clean -- %f
    	smudge = git-lfs smudge -- %f
    	process = git-lfs filter-process
    	required = true

    El fichero /home/<myuser>/.config/git/excludes equivale a un .gitignore aplicable a todos los repositorios.

    El alias fork devuelve el hash del commit en el que diverge la rama actual de main si no se proporciona ninguna rama. Si se proporciona una rama devuelve el hash del commit en el que diverge la rama proporcionada de main. Y si se proporcionan dos ramas devuelve el hash del commit en el que la segunda rama diverge de la primera rama proporcionada. Ejemplos:

          E---F---G rama HEAD
         /
    A---B---C---D main
             \
              H---I otra_rama

    Estando HEAD en el commit G, fork master devuelve el hash del commit B, es decir, el commit en el que la rama actual diverge de la rama indicada.

    $ git fork
    <hash del commit B>
    $ git fork otra_rama
    <hash del commit C>
    $ git fork rama otra_rama
    <hash del commit B>

    El alias showfork hace un show del commit en el que divergen las ramas indicadas. Y el alias difffork hace un diff entre el commit en el que divergen las ramas indicadas y el commit referido por la última de las ramas indicadas.

  • Mover una transacción git a otra rama

    ¿Nunca has hecho una transacción en git y te has dado cuenta que deberías haberla puesto en otra rama? Yo lo hago todos los días.

    Afortunadamente, es posible arreglar esto y dejarlo tal como si hubieras sido tan estrictamente riguroso en el control del árbol de cambios como se supone que se debe ser. La verdad es que yo sigo sin entender muchos detalles de cómo funciona git, pero parece que cualquier cosa que puedas imaginar o necesitar puede hacerse.

    Originalmente reproduje aquí los pasos para mover una transacción ya hecha hacia una nueva rama, tal como se indica a continuación. A posteriori recurrí a este mismo recurso para mover una transacción a otra rama ya existente, cuyos pasos incluyo en el segundo ejemplo.

    Los pasos (aparentemente más correctos) para mover la última transacción a una nueva rama son los siguientes:

    git co -b nueva_rama HEAD~1
    git branch --set-upstream-to=rama_original
    git cherry-pick ..rama_original
    git branch --force rama_original rama_original~1

    Créditos para esta respuesta en StackOverflow: Move the most recent commit(s) to a new branch with Git

    Si lo que se quiere es mover la transacción a una rama ya existente se haría así:

    git co rama_destino
    git cherry-pick rama_original~1..rama_original
    git branch --force rama_original rama_original~1
    

    Si no es solo una transacción sino varias seguidas se podría hacer cambiando el ~1 utilizado por el número de transacciones a mover.

    ¡Ojo!, si en el camino se han creado nuevas ramas o si se han subido (push) los cambios a un repositorio se pueden originar graves complicaciones, do it at  your own risk.

     

     

  • Deshacer un merge de git después de hacer un push como si no hubiera pasado nada

    La receta es simple, basta con devolver la rama erróneamente mezclada (merge) a su estado anterior y forzar la actualización en el repositorio (push).

    Sin embargo, hay que tener en cuenta que hay unos requisitos previos para garantizar que esto salga bien.

    1. Nadie, debe haber actualizado su espacio de trabajo con los cambios subidos al repositorio que queremos deshacer.
    2. El merge debe haberse hecho con la opción –no-ff (no fast-forward).
    3. No deben haberse realizado más commits después del del merge que queremos deshacer.

    De estos tres requisitos el primero es el más importante, si deshacemos estos cambios habiendo actualizado otra persona su espacio de trabajo con el contenido del repositorio estaremos creando dos universos paralelos divergentes.

    Los otros dos son más bien un «allá tú» si no los cumples. Es decir, puede que te funcione sin cumplirlos, pero si ese es tu caso, mejor mira en otros sitios donde se trate un caso más parecido al tuyo.

    Así que si estás seguro de que cumples estos requisitos solo tienes que ejecutar este par de comandos:

    git reset --hard <sha-commit-previo-a-merge>
    git push <repositorio> <rama> --force

    El sha-commit-previo-a-merge será la firma del commit previo al merge en la rama que queremos restaurar. Para saber exactamente cuál es el commit previo en la rama en la que hemos realizado el merge ejecutamos este comando:

    git log --first-parent <rama>

    El commit previo al del merge que se quiere deshacer (el actual si no hemos seguido haciendo commits, tal como indica el tercer requisito) será el que debemos proporcionar para el git reset.

    Y eso es todo. Las referencias que he consultado, entre otras, para atreverme a ejectuar esos comandos en mi repositorio son las siguientes: