Risposte:
Assicurati che il tuo albero di lavoro sia pulito, quindi
git reset --soft HEAD~3
git commit -m 'new commit message'
git reset --soft HEAD~3 && git commit -m "my message"
git config alias.mysquash '!f(){ git reset --soft HEAD~$1 && git commit ${2:+-m "$2"}; };f'
. git mysquash 3 'some message'
funzionerà, ma l'ho anche ottimizzato in modo git musquash 3
da omettere completamente il flag -m in modo da ottenere l' git commit
interfaccia utente interattiva in quel caso.
Personalmente mi piace la soluzione di Wilhelmtell :
git reset --soft HEAD~3
git commit -m 'new commit message'
Tuttavia, ho creato un alias con alcuni controlli di errore in modo che tu possa farlo:
git squash 3 'my commit message'
Consiglio di impostare alias che eseguano effettivamente gli script in modo che sia più facile (a) codificare gli script e (b) svolgere un lavoro più complesso con il controllo degli errori. Di seguito è riportato uno script che fa il lavoro di squash e poi di seguito è uno script per impostare gli alias git.
Script per schiacciare (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
Quindi per collegare lo script squash.sh a un alias git, crea un altro script per impostare i tuoi alias git in questo modo ( create_aliases.command o 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 '----------------'
$PATH
named git-squash.sh
e verrà automaticamente definito come alias git squash
. Non ho cambiato la tua risposta, nel caso ci fosse un motivo per usare la create-aiases.sh
sceneggiatura di cui non sono a conoscenza.
Per aggiungere alla risposta di Wilhelmtell, trovo conveniente eseguire il soft reset HEAD~2
e quindi modificare il commit di HEAD~3
:
git reset --soft HEAD~2
git commit --all --amend --no-edit
Questo unirà tutti i commit al HEAD~3
commit e utilizzerà il suo messaggio di commit. Assicurati di iniziare da un albero funzionante pulito.
Ero solito:
EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
Ha funzionato abbastanza bene. Basta non provare ad avere un registro di commit con una riga che inizia con "pick" :)
Usa il seguente comando per schiacciare gli ultimi 4 commit nell'ultimo commit:
git squash 4
Con 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
Da https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Ecco una riga per eliminare gli ultimi 2 commit. In questo esempio, il messaggio del penultimo commit verrà mantenuto. Puoi modificare il messaggio come desideri.
git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"
Questo comando sarà molto utile se crei un alias per questo comando e utilizzi invece l'alias.
Per schiacciare tutto da quando il ramo è stato biforcato dal maestro:
git reset --soft $(git merge-base --fork-point master) \
&& git commit --verbose --reedit-message=HEAD --reset-author
--reedit-message=HEAD
userà il messaggio dell'ultimo commit che non fa parte dello schiacciamento . Questo probabilmente non è quello che desideri. Per ottenere piuttosto il messaggio del primo commit da includere , (1) sostituire HEAD
con l'hash del commit di cui si desidera includere il messaggio, oppure (2) passare al primo commit da includere e git commit --amend --reedit-message=HEAD
. Questo è ciò che fa la risposta armoniosa.
Puoi avvicinarti abbastanza
git rebase --onto HEAD ~ 4 HEAD ~ master
Questo presume che tu sia in master con una storia lineare. Non è proprio uno squash perché scarta i commit intermedi. Dovresti modificare il nuovo HEAD per modificare il messaggio di commit.
HEAD~4
come genitore.