web-dev-qa-db-ja.com

多くのコミットを非対話的にスカッシュする方法はありますか?

さまざまなコミットを潰そうとしています-HEAD to HEAD〜3。これを行う簡単な方法はありますか、またはrebase --interactiveを使用する必要がありますか?

101
Phillip

作業ツリーがクリーンであることを確認してから、

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

私は個人的に wilhelmtell's ソリューションが好きです:

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

ただし、これを行うことができるように、いくつかのエラーチェックでエイリアスを作成しました。

git squash 3 'my commit message'

実際にスクリプトを実行するエイリアスを設定することをお勧めします。これにより、(a)スクリプトをコーディングし、(b)エラーチェックでより複雑な作業を行いやすくなります。以下は、スカッシュの作業を行うスクリプトです。次に、gitエイリアスを設定するためのスクリプトがあります。

スカッシュ用スクリプト(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

次に、そのsquash.shスクリプトをgitエイリアスに接続するには、次のようにgitエイリアスを設定する別のスクリプトを作成します(create_aliases.commandまたは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 '----------------'
30
n8tr

私が使用した:

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

かなりうまくいきました。 「pick」で始まる行でコミットログを取得しようとしないでください:)

9
Julien Wajsberg

wilhelmtell による回答に追加するには、HEAD~2にソフトリセットし、HEAD~3のコミットを修正すると便利です。

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

これにより、すべてのコミットがHEAD~3コミットにマージされ、そのコミットメッセージが使用されます。きれいな作業ツリーから始めてください。

8
harmonious

次のコマンドを使用して、最後のコミット内の最後の4つのコミットをスカッシュします。

git squash 4

エイリアスあり:

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 

から https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

3
brauliobo

これは、最後の2つのコミットを無効にする1つのライナーです。この例では、最後から2番目のコミットのメッセージが保持されます。必要に応じてメッセージを変更できます。

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

このコマンドは、このコマンドのエイリアスを作成し、代わりにエイリアスを使用する場合に非常に役立ちます。

2
Jasir

ブランチがマスターから分岐してからすべてをつぶすには:

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

かなり近づきます

git rebase --HEAD〜4 HEAD〜マスターへ

これは、履歴が線形であるマスターを前提としています。中間コミットを破棄するため、完全なスカッシュではありません。コミットメッセージを変更するには、新しいHEADを修正する必要があります。

0
Greg Bacon