Jawaban:
Pastikan pohon kerja Anda bersih, lalu
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'
akan berfungsi, tetapi saya juga mengubahnya sehingga git musquash 3
akan menghilangkan -m sepenuhnya sehingga Anda akan mendapatkan git commit
UI interaktif dalam kasus itu.
Saya pribadi menyukai solusi wilhelmtell :
git reset --soft HEAD~3
git commit -m 'new commit message'
Namun, saya membuat alias dengan beberapa pengecekan kesalahan sehingga Anda bisa melakukan ini:
git squash 3 'my commit message'
Saya sarankan menyiapkan alias yang benar-benar menjalankan skrip sehingga lebih mudah untuk (a) membuat kode skrip Anda dan (b) melakukan pekerjaan yang lebih kompleks dengan pemeriksaan kesalahan. Di bawah ini adalah skrip yang melakukan pekerjaan squash dan di bawahnya adalah skrip untuk menyiapkan alias git Anda.
Script untuk squash (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
Kemudian untuk menghubungkan skrip squash.sh itu ke alias git, buat skrip lain untuk menyiapkan alias git Anda seperti itu ( create_aliases.command atau 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
nama git-squash.sh
dan secara otomatis akan diberi nama alias git squash
. Saya tidak mengubah jawaban Anda, kalau-kalau ada alasan untuk menggunakan create-aiases.sh
skrip yang tidak saya ketahui.
Untuk menambah jawaban oleh wilhelmtell, saya merasa nyaman untuk melakukan soft reset HEAD~2
dan kemudian mengubah komit HEAD~3
:
git reset --soft HEAD~2
git commit --all --amend --no-edit
Ini akan menggabungkan semua komit ke HEAD~3
komit dan menggunakan pesan komitnya. Pastikan untuk memulai dari pohon kerja yang bersih.
Saya menggunakan:
EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
Bekerja dengan baik. Hanya saja, jangan mencoba memiliki log komit dengan baris yang dimulai dengan "pilih" :)
Gunakan perintah berikut untuk menghentikan 4 komit terakhir dalam komit terakhir:
git squash 4
Dengan 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
Dari https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Berikut ini adalah satu baris untuk menghentikan 2 komit terakhir. Dalam contoh ini, pesan dari komit terakhir kedua akan disimpan. Anda dapat mengubah pesan sesuai keinginan Anda.
git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"
Perintah ini akan sangat berguna jika Anda membuat alias untuk perintah ini dan menggunakan alias sebagai gantinya.
Untuk menghancurkan segalanya sejak cabang itu bercabang dari master:
git reset --soft $(git merge-base --fork-point master) \
&& git commit --verbose --reedit-message=HEAD --reset-author
--reedit-message=HEAD
akan menggunakan pesan dari komit terakhir yang bukan bagian dari squashing . Ini mungkin bukan yang Anda inginkan. Untuk mendapatkan pesan dari komit pertama yang akan disertakan , baik (1) ganti HEAD
dengan hash komit yang Anda inginkan pesannya, atau (2) lompat ke komit pertama untuk disertakan dan git commit --amend --reedit-message=HEAD
. Inilah yang dilakukan oleh jawaban yang harmonis.
Anda bisa cukup dekat dengan
git rebase --untuk HEAD ~ 4 HEAD ~ master
Ini mengasumsikan Anda menguasai dengan sejarah linier. Ini bukan squash karena membuang komitmen perantara. Anda perlu mengubah HEAD baru untuk mengubah pesan komit.
HEAD~4
dijadikan induknya.