¿Hay alguna manera de aplastar una cantidad de commits de forma no interactiva?

Estoy intentando aplastar un range de commits: HEAD to HEAD ~ 3. ¿Hay una manera rápida de hacerlo, o necesito usar rebase –interactive?

Asegúrate de que tu tree de trabajo esté limpio, luego

git reset --soft HEAD~3 git commit -m'new commit message' 

Personalmente me gusta la solución de wilhelmtell :

 git reset --soft HEAD~3 git commit -m 'new commit message' 

Sin embargo, hice un alias con alguna comprobación de errores para que pueda hacer esto:

 git squash 3 'my commit message' 

Recomiendo configurar alias que realmente ejecutan scripts para que sea más fácil (a) codificar tus scripts y (b) hacer un trabajo más complejo con la comprobación de errores. A continuación se muestra un script que hace el trabajo de squash y luego debajo que es un script para configurar tus alias de git.

Script para aplastar (squash.sh)

 #!/bin/sh # #get number of commits to squash squashCount=$1 #get the commit message shift commitMsg=$@ #regular expression to verify that squash number is an integer regex='^[0-9]+$' echo "---------------------------------" echo "Will squash $squashCount commits" echo "Commit message will be '$commitMsg'" echo "...validating input" if ! [[ $squashCount =~ $regex ]] then echo "Squash count must be an integer." elif [ -z "$commitMsg" ] then echo "Invalid commit message. Make sure string is not empty" else echo "...input looks good" echo "...proceeding to squash" git reset --soft HEAD~$squashCount git commit -m "$commitMsg" echo "...done" fi echo exit 0 

Luego, para conectar ese script squash.sh a un git alias, cree otro script para configurar sus alias de git como así ( create_aliases.command o create_aliases.sh ):

 #!/bin/sh echo '-----------------------' echo 'adding git aliases....' echo '-----------------------' echo git config --global alias.squash "!sh -c 'sh <path to scripts directory>/squash.sh \$1 \$2' -" #add your other git aliases setup here #and here #etc. echo '------------------------------------' echo 'here is your global gitconfig file:' echo '------------------------------------' more ~/.gitconfig echo echo echo '----------------' echo 'end of script...' echo '----------------' 

Solía:

 EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref> 

Funcionó bastante bien. Simplemente no intente tener un logging de compromiso con una línea que comience con "elegir" 🙂

Use el siguiente command para aplastar los últimos 4 commits dentro del último commit:

 git squash 4 

Con el alias:

 squash = !"f() { NL=$1; GIT_EDITOR=\"sed -i '2,$NL s/pick/squash/;/# This is the 2nd commit message:/,$ {d}'\"; git rebase -i HEAD~$NL; }; f" sq = !git squash $1 sqpsf = !git squash $1 && git psf 

Desde https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

Para agregar a la respuesta de wilhelmtell encuentro conveniente reiniciar suavemente HEAD ~ 2 y luego modificar la confirmación de HEAD ~ 3:

 git reset --soft HEAD~2 git commit --all --amend --no-edit 

Esto fusionará todas las confirmaciones con la confirmación HEAD ~ 3 y usará su post de confirmación. Asegúrese de comenzar desde un tree de trabajo limpio.

Aquí hay un trazador de líneas para aplastar los últimos 2 commits. En este ejemplo, se conservará el post de la segunda última confirmación. Puede cambiar el post como lo desee.

 git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)" 

Este command será muy útil si crea un alias para este command y usa el alias en su lugar.

Puedes acercarte bastante

  git rebase --onto HEAD ~ 4 HEAD ~ master 

Esto supone que estás en el maestro con una historia lineal. No es una calabaza porque descarta los compromisos intermedios. Debería modificar el nuevo HEAD para modificar el post de confirmación.