web-dev-qa-db-fra.com

Existe-t-il un moyen d'écraser un certain nombre de commits de manière non interactive?

J'essaie d'écraser une série de commits - HEAD à HEAD ~ 3. Existe-t-il un moyen rapide de procéder ou dois-je utiliser rebase --interactive?

92
Phillip

Assurez-vous que votre arbre de travail est propre, puis

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

Personnellement, j'aime bien la solution de { wilhelmtell }:

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

Cependant, j'ai créé un alias avec une vérification d'erreur afin que vous puissiez le faire:

git squash 3 'my commit message'

Je recommande de configurer des alias qui exécutent des scripts afin de faciliter (a) la programmation de vos scripts et (b) d'effectuer un travail plus complexe avec la vérification des erreurs. Vous trouverez ci-dessous un script qui effectue le travail de squash, puis un script pour configurer vos alias git.

Script pour écraser (squash.sh)

#!/bin/bash
#

#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

Ensuite, pour associer ce script squash.sh à un alias git, créez un autre script pour configurer votre alias git comme suit (create_aliases.command ou create_aliases.sh):

#!/bin/sh
echo '-----------------------'
echo 'adding git aliases....'
echo '-----------------------'
echo
git config --global alias.squash "!bash -c 'bash <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 '----------------'
29
n8tr

J'ai utilisé:

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

Travaillé assez bien. Juste n'essayez pas d'avoir un journal de commit avec une ligne qui commence par "pick" :)

7
Julien Wajsberg

Pour ajouter à la réponse de wilhelmtell Je trouve pratique de réinitialiser manuellement le code à HEAD~2 puis de modifier le commit de HEAD~3:

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

Cela va fusionner tous les commits avec le commit HEAD~3 et utiliser son message de commit. Assurez-vous de partir d'un arbre de travail propre.

7
harmonious

Utilisez la commande suivante pour écraser les 4 derniers commits dans le dernier commit:

git squash 4

Avec l'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 

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

3
brauliobo

Voici un one-liner pour écraser les 2 derniers commits. Dans cet exemple, le message de l'avant dernier commit sera conservé. Vous pouvez modifier le message à votre guise.

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

Cette commande sera très utile si vous créez un alias pour cette commande et utilisez-le à la place.

2
Jasir

Pour tout écraser depuis que la branche est passée du maître:

git reset --soft $(git merge-base --fork-point master) \
  && git commit --verbose --reedit-message=HEAD --reset-author
0
Andy

Vous pouvez être assez proche avec

git rebase --onto HEAD ~ 4 HEAD ~ maître

Cela suppose que vous êtes sur maître avec une histoire linéaire. Ce n'est pas tout à fait une courge, car elle supprime les commits intermédiaires. Vous devez modifier le nouveau HEAD pour modifier le message de validation.

0
Greg Bacon