これを行うための組み込み機能はありません。独自のスクリプトを作成する必要があります。
これを行うには、git rev-list
orから始めてgit log
(どちらも基本的に同じことを行いますが、コマンドライン オプションが多少異なります)、スキャンするすべてのコミットを繰り返し処理します。ここでの目標は、コミットを新しい一時ブランチにコピーしてスカッシュすることです。たとえば、コミットがすべて branch で行われ、 branchfeature
にマージされると仮定するtarget
と、検査するコミットのリストを取得できます。
git rev-list --reverse --topo-order target..feature > /tmp/list
ここでの出力は、コミット SHA-1 ID のリストです。コミットごとに、作成者とおそらくコミットメッセージを見つけたいと思うでしょう:
while read sha1; do
author_name=$(git log -n 1 --format=%an $sha1)
...
done < /tmp/list
現在の作成者名が以前の作成者名と同じ場合は、このコミットを蓄積したいだけですが、異なる場合はコミット ID を発行したいと考えています。は最初は設定されていないため$author_name
、空の文字列になるため、最初のコミットは前の作成者と一致しませんが、常に最初のコミットを蓄積し、アクションを実行する必要があるため、これを特別に処理する必要があります (最終コミット ID と共に)。最後のコミット後または作成者の変更時。したがって、...
セクションは少し複雑です。また、最初のコミットが branch の先端を指す一時的なブランチを作成して取得するためのセットアップ作業も必要target
です。名前付きの一時ブランチを使用するのではなく、ここでは匿名のブランチを使用します。
最後に、押しつぶされたコミットを作成する方法は特に注意が必要です。これを行う簡単な方法は、配管コマンド を使用してgit commit-tree
から、一時ブランチを進めることです。
これらすべてをまとめると、次の完全にテストされていないコードが得られます。
# add new squash-style commit using commit $1
make_squash_commit() {
local sha1=$1 tree new_sha1
tree=$(git rev-parse $sha1^{tree})
new_sha1=$(git commit-tree $tree -p HEAD)
git update-ref -m "squash $sha1" HEAD $new_sha1
}
set -e
git rev-list --reverse --topo-order target..feature > /tmp/list
git checkout --detach target
: > /tmp/accum_log
prev_sha1=""
while read sha1; do
author_name=$(git log -n 1 --format=%an $sha1)
if [ "$author_name" != "$prev_name" -a -n "$prev_sha1" ]; then
make_squash_commit $prev_sha1 < /tmp/accum_log
: > /tmp/accum_log
fi
prev_name="$author_name"
prev_sha1=$sha1
git log -n 1 --format="%B" $sha1 >> /tmp/accum_log
done < /tmp/list
if [ -z "$prev_sha1" ]; then
echo "Warning: no commits found to squash!"
sha1=$(git rev-parse target)
fi
# squash final commit, then give anonymous branch a name
make_squash_commit $prev_sha1 < /tmp/accum_log
git checkout -b temp_branch
rm /tmp/list /tmp/accum_log
このスクリプトにはやや意図的な欠陥があります: 現在の日付と時刻を使用して、それぞれの作成者およびコミッターとしてのすべての新しいコミットを作成します(複数の作成者のコミットを混乱させ、押しつぶすため、これは適切です)。同意したかどうかに関係なく)。ステップで適切な環境変数をすべて設定することで、これを「修正」できますgit commit-tree
(ドキュメントを参照)。