未来エンジニア養成所Blog

プログラミングを皆に楽しんでもらうための情報をお届けします。

【Git&GitHub】リベースで履歴を書き換える Part2

title


リベースで履歴を書き換える

今回はリベースで履歴を書き換えるやり方の続きを解説します。


前回は複数のコミットの履歴を書き換えました。

今回はコミットを並び替えたり、コミットをまとめたり、逆にコミットを分割するやり方について解説します。


コミットを並び替える、削除する

まずコミットを並び替えたり、削除する方法について解説します。

そのためにはまず「git rebase -i」コマンドを使います。

前回と同じように

$ git rebase -i HEAD~3

と指定しましょう。

すると前回と同じように3つのコミットが表示されます。

pick gh21f6d ヘッダー修正
pick 193054e ファイル追加
pick 84gha0d README修正

ちなみにこの表示の仕方は「git log」とは逆なので、注意してください。


「git log」の場合は一番先頭のものから上から順に表示されましたが、今回は逆順になります。

つまり、README修正というのが一番最近のコミットで、その親コミットが「ファイル追加」さらにその親コミットが「ヘッダー修正」となっています。


では今回はこの履歴を削除したり、並び替えたりしてみましょう。


まずコミットの削除からやってみます。

「README修正」のコミットを消したいとします。

その場合は「README修正」の行をコミットエディタ上で消してあげればOKです。

pick gh21f6d ヘッダー修正
pick 193054e ファイル追加


次に、コミットの並び替えをします。

「ヘッダー修正」と「ファイル追加」の適用の順番を変えていきましょう。

その場合もコミットエディタ上でコミットの順番を入れ替えてあげればコミットの順番を変更することができます。

pick 193054e ファイル追加
pick gh21f6d ヘッダー修正


このようにコミットを削除したい場合はそのコミットの行を消して、コミットの順番を入れ替えたい場合は単純にコミットの順番を入れ替えてあげればOKです。


実際にやってみよう(コミットを並び替える)

それではターミナル上で確かめていきましょう。

まず今のGitの状態を確かめます。

$ git log --oneline -n 3
afe8acc (HEAD -> main) third.html
5e155d7 second.htmlを追加
8d41a2e first.htmlを追加

すると前回の通りです。


3つコミットが最新のものでされていて、「third.html」「second.htmlを追加」「first.htmlを追加」となっています。


今回このログの順番を変えていこうと思います。

$ git rebase -i HEAD~3

コミットエディタが立ち上がります。

pick 8d41a2e first.htmlを追加
pick 5e155d7 second.htmlを追加
pick afe8acc third.html

ここで注目して欲しいのは「git log」とは逆の順番で表示されていると言うことです。

どのような順番で表示されているかというと、リベースを適用するコミット順に表示されています。

「git rebase -i」コマンドは基盤となるコミットがあって、そのコミット以降のコミットが書かれている、その元となるコミット以降のものを順にリベースしていくので、このような順番で表示されています。


それでは今回は「second.htmlを追加」というコミットを一番古いところに持ってきてみましょう。

pick 5e155d7 second.htmlを追加
pick 8d41a2e first.htmlを追加
pick afe8acc third.html

このように「second.htmlを追加」というのを一番古い履歴(一番上)に持ってきてみました。

これでコミットの順番を入れ替えた場合の挙動についてみてみます。


保存してテキストエディタを終了します。

ターミナルに戻ります。

$ git rebase -i HEAD~3
Successfully rebased and updated refs/heads/main.

ターミナルに戻るとリベースが成功しています。

それでは「git log」でコミットの順番が入れ替えられているか確認してみましょう。

$ git log --oneline -n 3
c89918b (HEAD -> main) third.html
ce67305 first.htmlを追加
08eb2b7 second.htmlを追加


すると先ほどとは違って、git logの順番が「second.htmlを追加」が一番古い履歴になっています。

このように「git rebase -i」コマンドを使ってコミットエディタ上で順番を入れ替えることでコミットの順番を入れ替えることができました。


コミットをまとめる

次に、コミットをまとめるやり方について解説します。


まずいつも通り「git rebase -i HEAD~3」と入力します。

するとコミットエディタが立ち上がるので、そこに今回は「pick」の代わりに「squash」と入力します。

「squash」というのは押しつぶすとかぺちゃんこにするという意味です。

この「squash」をして、リベースするとそのコミットを直前のコミットと一つにしてコミットを1つにまとめることができます。


例えば、今回みたいに3つのコミットを1つにまとめたい場合でしたら、一番新しいコミットをそのまま「pick」にしておいて、残りのコミットを「squash」にしてあげればコミットを1つにまとめることができます。


実際にやってみよう(コミットをまとめる)

それではターミナルにもどって実際にやっってみましょう。

$ git rebase -i HEAD~3

と入力します。


今回はこの3つのコミットを1つにまとめてみます。

2つ目以降の「pick」という文字を「squash」と変更しましょう。

pick 08eb2b7 second.htmlを追加
squash ce67305 first.htmlを追加
squash c89918b third.html

保存してコミットエディタを終了します。

ターミナルに戻ります。

ターミナルに戻ろうとしたら、もう一度コミットエディタが立ち上がりました。

「squash」の場合コミットをまとめたよというのがコミットメッセージとして記録されます。

今回はここで表示されているコミットメッセージをそのまま保存して終了します。


ではターミナルに戻ります。

$ git rebase -i HEAD~3
[detached HEAD 70edcc6] second.htmlを追加
 Date: Wed Sep 1 17:03:51 2021 +0900
 3 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 first.html
 create mode 100644 second.html
 create mode 100644 third.html
Successfully rebased and updated refs/heads/main.

ターミナルに戻るとリベースが上手くいっていることが確認できます。

それでは「git log」でコミットの状態をみてみましょう。

$ git log --oneline -n 3
70edcc6 (HEAD -> main) second.htmlを追加
966020f (origin/main) feature2を新規作成
b638345 main2を新規作成

すると、先ほどまで3つあった「〜.htmlを追加」というのが、「second.hemlを追加」という1つのコミットになっています。

これでコミットが1つになっていることが確認できました。

ファイルも元の通りあるのか、本当にコミットが1つに纏まっただけなのかとういうのを確認してみましょう。

$ ls
feature.html    first.html  index.html  main2.html  secret.txt
feature2.html   home.html   main.html   second.html third.html

すると「first.html」も「second.html」も「third.html」もあることが確認できます。

これで確かにコミットが1つに纏まったことが確認できました。

このようにsquashをつかうことでコミットを1つにまとめることができます。


コミットを分割する

最後にコミットを分割するやり方について解説します。

またいつも通り「git rebase -i HEAD~3」と入力します。

pick gh21f6d ヘッダー修正
pick 193054e ファイル追加
pick 41ghaOd READMEとindex修正

今回、コミットの3番目のコミットを見てください。

すると今回は「READMEとindex修正」とコミットメッセージが書かれています。


このコミットでは2つの事をやって、それを一つのコミットにしてしまったという状況です。

今回、その「READMEとindex修正」というのを「README修正」と「index修正」という2つのコミットに分割したいと思います。


それでは分割するやり方を見ていきましょう。

分割するためには分割したいコミットの「pick」を「edit」に書き換えます。

今回ですと「READMEとindex修正」というコミットのところを「edit」に書き換えます。

書き換えたら保存してコミットエディタを終了します。

終了したらまず

$ git reset HEAD^

と入力します。

これは何かというと、「git reset」コマンドというのがコミットを取り消して、ステージングしていない状況にまで戻すコマンドです。

「HEAD^」というのが「edit」と記載しているコミットのことを指します。

「git reset HEAD^」と入力することで、「edit」と記載されているコミットのコミットを取り消して、さらにステージングもしていない状態にまで戻すというコマンドになります。

このコマンドでコミットを取り消してステージもしていない状態に戻したら、「README修正」というのと「index修正」というのをそれぞれでコミットしていきます。


まずREADMEからいきましょう。

$ git add README

でステージに追加して

$ git commit

していきます。

コミットメッセージは「README修正」とします。

これで「README修正」のコミットはできたので、次にindex.htmlの方をコミットしていきます。

$ git add index.html

そして

$ git commit

します。

コミットメッセージは「index.html修正」とします。

こうすることで2つのコミットに分割できました。


これでコミットまでできたので、次はリベースを次のコミットに進めるために

$ git rebase --continue

コマンドを入力します。

これでコミットは分割できます。


実際にやってみよう(コミットを分割する)

それではターミナルに戻って作業していきましょう。

まず今の状態をもう一度確認しておきます。

$ git log --oneline -n 3
70edcc6 (HEAD -> main) second.htmlを追加
966020f (origin/main) feature2を新規作成
b638345 main2を新規作成

すると「second.htmlを追加」というコミットで、前回の操作で3つのコミットが1つにまとめられています。

今回それを2つのコミットに分割していこうと思います。

$ git rebase -i HEAD~3


pick b638345 main2を新規作成
pick 966020f feature2を新規作成
pick 70edcc6 second.htmlを追加

今回は一番最新のコミットである「second.htmlを追加」というのを分割したいので、これを「pick」から「edit」に書き換えます。

書き換えたら保存して終了します。


ターミナルに戻ります。

まずはresetコマンドでコミットの取り消しをしていきましょう。

$ git reset HEAD^

これでコミットの取り消しとステージングしていない状態にすることができているはずです。

$ git status
interactive rebase in progress; onto c378922
Last commands done (3 commands done):
   pick 966020f feature2を新規作成
   edit 70edcc6 second.htmlを追加
  (see more in file .git/rebase-merge/done)
No commands remaining.
You are currently editing a commit while rebasing branch 'main' on 'c378922'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    first.html
    second.html
    third.html

nothing added to commit but untracked files present (use "git add" to track)

すると、「first.html」「second.html」「third.html」がステージングされていない状態になっていることがわかります。

これを今回「first.html second.htmlを追加」というコミットと「third.htmlを追加」という2つのコミットに分割してみましょう。


まず「first.html」「second.html」を追加というコミットをつくっていきます。

$ git add first.html

$ git add second.html

これをコミットしていきます。

$ git commit -m 'first.htmlとsecond.htmlを追加'

[detached HEAD 1b62b2c] first.htmlとsecond.htmlを追加
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 first.html
 create mode 100644 second.html

コミットできました。


それでは続いて「third.html」 のコミットもやっていきましょう。

$ git add third.html

ではコミットしていきます。

$ git commit -m 'third.htmlを追加'
[detached HEAD 55c46b4] third.htmlを追加
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 third.html

これで追加できました。


2つのコミットができたので、続けていきます。

$ git rebase --continue
Successfully rebased and updated refs/heads/main.

これで次のリベースへ進んでいきます。


これでリベースが完了です。

「git log」コマンドで確認してみましょう。

$ git log --oneline -n 3
55c46b4 (HEAD -> main) third.htmlを追加
1b62b2c first.htmlとsecond.htmlを追加
966020f (origin/main) feature2を新規作成

すると、「third.htmlを追加」と「first.htmlとsecond.htmlを追加」という2つのコミットに分割されていることが確認できました。


このようにリベースコマンドを使うことで、コミットの順番を入れ替えたり、コミットをまとめたり、逆にコミットを分割したりすることができます。


リベースの内容としてはここまでですが、一番最後にGitHubに今回の内容をアップしておきましょう。

$ git push origin main
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 518 bytes | 259.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:piketa/git_tutorial.git
   966020f..55c46b4  main -> main


参考図書



独学で挫折しそうになったら、オンラインプログラミングスクール
未来エンジニア養成所Logo



あわせて学習したい

phoeducation.work