Git スカッシュコミット
このチュートリアルでは、Git スカッシュについて学習します。基本的な考え方は、複数の連続したコミットを取り、それらを 1つに押しつぶすことです。
主な目的は、多くのコミットをいくつかの関連するコミットに凝縮することです。したがって、これを行うと、git の履歴が簡潔で明確に見えます。
別の見方をすれば、あるタスクに関連する複数のコミットを実行することです。しばらくして、満足のいく状態に達すると、多くのコミットメッセージが git の履歴を乱雑にします。
この時点で、さまざまなコミットを 1つにまとめて、git の履歴が明確になり、実行されたタスクを最もよく反映するようにすることができます。
もう 1つの使用例は、ブランチのマージを実行しながらスカッシュを実行することです。通常、一部の機能開発のために、メインブランチから機能ブランチを作成します。
機能の完了後、機能ブランチをメインブランチにマージします。ここでも、メインブランチにマージするときに、機能ブランチで行われたさまざまなコミットメッセージを 1つにまとめたい場合があります。
git squash
コマンドがないことに注意してください。
Git スカッシュを実現するには 2つの方法があります。
- コミットを潰すために使用されるインタラクティブツールとしての
git rebase -i
- マージ中に
-squash
オプションを使用するgit merge -squash
対話的な git rebase
ツールによる Git コミットのスカッシュ
次の git log
を見てみましょう。これは、押しつぶすことに関心がある HEAD
からの最後の 4つのコミットを示しています。
25c38c4 remove .class files
da66e6a Delete version.ini
f4e3f09 Delete .log
b0e6655 Delete .lock
da66e6a github git notes
ログには、関係のないさまざまなファイルを削除する操作を示す最初の 4つのコミットメッセージが表示されます。次に、これら 4つのコミットを 1つにまとめます。
以下は、インタラクティブリベースツールを使用して最後の X コミットを押しつぶすコマンドの構文です。
git rebase -i HEAD~[X]
したがって、4つのコミットを潰すには、次のようにします。
$ git rebase -i HEAD~4
このコマンドを発行した後、Git は、以下に示すように、スカッシュへのコミットの詳細を含むデフォルトのエディターを呼び出します。
pick b0e6655 Delete .lock
pick f4e3f09 Delete .log
pick da66e6a Delete version.ini
pick 25c38c4 remove .class files
# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
エディターは、pick
コマンドを使用してさまざまなコミットを表示します。また、使用可能なコマンドに関する情報も表示されます。squash
(または s
)コマンドを使用します。
以下に示すように、最初のコミットは pick
コマンドで保持し、残りの 3つのコミットでは pick
から s
(スカッシュの場合)コマンドに変更します。
pick b0e6655 Delete .lock
s f4e3f09 Delete .log
s da66e6a Delete version.ini
s 25c38c4 remove .class files
# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
...
squash
(または s
)でマークされたコミットは、メインのコミットにマージされます。pick
でマークされたもの。
次に、変更をエディターに保存して終了します。この後、rebase -i
ツールは、以下のように、コミットメッセージを入力するための別のエディターを開きます。
# This is a combination of 4 commits. The first commit's message is:
Delete .lock
# This is the 2nd commit message:
Delete .log
# This is the 3rd commit message:
Delete version.ini
# This is the 4th commit message:
remove .class files
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sun Jan 3 16:39:23 2021 +0530
#
# interactive rebase in progress; onto 652d2fe
# Last commands done (4 commands done):
# pick b0e6655 Delete .lock
# s f4e3f09 Delete .log
# s da66e6a Delete version.ini
# s 25c38c4 remove .class files
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '652d2fe'.
#
# Changes to be committed:
# new file: github-git-notes.txt
#
ここで、最初のコミットメッセージの先頭に新しいコミットメッセージを追加します。
Deleted irrelevant files
# This is a combination of 4 commits. The first commit's message is:
Delete .lock
# This is the 2nd commit message:
Delete .log
...
保存してエディタを終了すると、rebase -i
ツールは次のメッセージを出力します。
HEAD~2
Rebasing (2/2)
[detached HEAD caab6e8] Deleted irrelevant files
Date: Sun Jan 3 16:39:23 2021 +0530
1 file changed, 54 insertions(+)
create mode 100644 github-git-notes.txt
Successfully rebased and updated refs/heads/master.
ここで、git log
を確認し、4つのコミットメッセージではなく、squashed
コミット(つまり)単一のコミットメッセージを確認します。
$ git log --oneline
25c38c4 Deleted irrelevant files
da66e6a github git notes
...
git merge -squash
を使用して Git コミットをスカッシュする
以下は、ブランチを現在のブランチ(通常は main
)とマージし、ソースブランチのコミットを潰すためのコマンドの構文です。
git merge --squash <source_branch_name_to_squash>
ここで、機能ブランチをマージします。feature1``main
ブランチで押しつぶします。
まず、メイン
ブランチにチェックアウト
します。
$ git checkout main
Switched to branch 'main'
次に、次のように squash
オプションを使用して git merge
を実行します。
$ git merge --squash feature1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
--squash
オプションを指定して merge
を実行すると、Git は通常のマージの場合のように、宛先ブランチにマージコミットを作成しません。代わりに、Git はソースブランチのすべての変更を取得します。feature1
そしてそれを宛先ブランチの作業コピーである main
にローカルな変更として反映させます。
下記を参照してください。
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: config.ini
ここで、ファイル config.ini
には、feature1
ブランチで行われた変更が含まれています。
残っているのは、以下のように main
ブランチに変更をコミットすることだけです。
$ git commit -am 'Merged and squashed the feature1 branch changes'
[main 573b923] Squashed and merged the feature1 branch
1 file changed, 4 insertions(+)
したがって、feature1
ブランチのコミットメッセージを潰すこととともに、feature1
ブランチの変更を main
ブランチにマージしました。現在、main
ブランチにはコミットメッセージが 1つだけあります。
関連記事 - Git Rebase
- Git Rebase Origin/Branch と Git Rebase Origin Branch の比較
- Git で特定のコミットにリベースする
- コマンド ラインで Git Rebase を使用する
- Git ブランチをリベース
- Git のリモートリポジトリブランチから変更をプルするときにローカルブランチをリベースする