Câu trả lời:
Đảm bảo cây làm việc của bạn sạch sẽ, sau đó
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'
sẽ hoạt động, nhưng tôi cũng đã chỉnh sửa nó nên git musquash 3
sẽ loại bỏ hoàn toàn cờ -m, do đó bạn sẽ nhận được git commit
giao diện người dùng tương tác trong trường hợp đó.
Cá nhân tôi thích giải pháp của wilhelmtell :
git reset --soft HEAD~3
git commit -m 'new commit message'
Tuy nhiên, tôi đã tạo một bí danh với một số lỗi kiểm tra để bạn có thể thực hiện việc này:
git squash 3 'my commit message'
Tôi khuyên bạn nên thiết lập bí danh thực sự chạy các tập lệnh để (a) viết mã các tập lệnh của bạn dễ dàng hơn và (b) thực hiện công việc phức tạp hơn với việc kiểm tra lỗi. Dưới đây là một tập lệnh thực hiện công việc của bí và sau đó là tập lệnh để thiết lập bí danh git của bạn.
Script cho squashing (bí.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
Sau đó, để kết nối tập lệnh squash.sh đó với bí danh git, hãy tạo một tập lệnh khác để thiết lập bí danh git của bạn như vậy ( create_aliases.command hoặc 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
tên git-squash.sh
và nó sẽ được tự động bí danh như git squash
. Tôi đã không thay đổi câu trả lời của bạn, đề phòng có lý do để sử dụng create-aiases.sh
tập lệnh mà tôi không biết.
Để thêm vào câu trả lời của wilhelmtell, tôi thấy thuận tiện khi đặt lại mềm HEAD~2
và sau đó sửa đổi cam kết của HEAD~3
:
git reset --soft HEAD~2
git commit --all --amend --no-edit
Điều này sẽ hợp nhất tất cả các cam kết với HEAD~3
cam kết và sử dụng thông điệp cam kết của nó. Đảm bảo bắt đầu từ một cây làm việc sạch sẽ.
Tôi đã sử dụng:
EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
Làm việc khá tốt. Chỉ cần không cố gắng có một bản ghi cam kết với một dòng bắt đầu bằng "pick" :)
Sử dụng lệnh sau để loại bỏ 4 lần cam kết cuối cùng trong lần cam kết cuối cùng:
git squash 4
Với bí danh:
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
Từ https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Đây là một lớp lót để xóa 2 cam kết cuối cùng. Trong ví dụ này, thông báo của lần cam kết cuối cùng thứ hai sẽ được giữ lại. Bạn có thể thay đổi thông báo như bạn muốn.
git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"
Lệnh này sẽ rất hữu ích nếu bạn tạo bí danh cho lệnh này và sử dụng bí danh thay thế.
Để thu gọn tất cả mọi thứ kể từ khi nhánh được chia từ chủ nhân:
git reset --soft $(git merge-base --fork-point master) \
&& git commit --verbose --reedit-message=HEAD --reset-author
--reedit-message=HEAD
sẽ sử dụng thông báo của lần cam kết cuối cùng mà không phải là một phần của quá trình xử lý . Đây có thể không phải là cái bạn muốn. Để thay thế thông điệp của cam kết đầu tiên được đưa vào , hãy (1) thay thế HEAD
bằng băm của cam kết mà bạn muốn thông báo hoặc (2) chuyển đến cam kết đầu tiên được đưa vào và git commit --amend --reedit-message=HEAD
. Đây là những gì câu trả lời hài hòa 'làm.
Bạn có thể đến khá gần với
git rebase --onto HEAD ~ 4 HEAD ~ master
Điều này giả định rằng bạn đang nắm vững một lịch sử tuyến tính. Nó không hoàn toàn bí vì nó loại bỏ các cam kết trung gian. Bạn cần phải sửa đổi HEAD mới để sửa đổi thông báo cam kết.
HEAD~4
làm cha mẹ của nó.