【git】git stash の使い方を具体例を使ってわかりやすくしてみた


はじめに

Git Hubを使用するときに、次のようなことありませんか。

  • プルリクして他の人に確認をしてもらっている時にそのプルリクの内容を使用して開発を続けたい。

  • 作業するブランチを間違えて本来作業したいブランチにその作業した内容を反映させたい。

そんなときにstashというコマンドが便利のなので使用例と共に紹介していこうと思います。
git初心者のためもっと便利な方法がありましたら指摘してただけると幸いです。

前提として

  • git hub の基本的な使い方(comit,push,pullなど)が分かっていること

私の使用している環境

  • pc:macOS Catalina 10.15.7
  • 統合開発環境:atom version1.50.0

stashについて

stashとは・・・
一言で言うとコミットからの変更履歴をstash listに避難(保持)ができるコマンドです。

具体例を使用して説明していきます。

大まかな手順をまとめておきます。

  • 手順①Aブランチをつくってtest1.pyプルリクエスト
  • 手順②プルリクエスト後Aブランチのままtest1.pyに内容を追加
  • 手順③test1.pyに追加した内容をgit stash listに避難させる
  • 手順④git stash list でstashした内容の確認
  • 手順⑤新しいブランチを作成(Bブランチ作成)
  • 手順⑥リモートの内容をBブランチにpullする(Aブランチの状態によってpullしてくる箇所が異なる)
  • 手順⑦git stash listの内容を反映することができるコマンドを確認
  • 手順⑧git stash listの内容を反映する

手順①Aブランチをつくってtest1.pyプルリクエスト

masterブランチからAブランチを作成後、以下のファイルをコミットしてプルリクエストをした。

test1.py
# 最初のコミット
print("test1")

次にプルリクエストを待っている間にコミットしたファイルを使用したい。

手順②プルリクエスト後Aブランチのままtest1.pyに内容を追加

Aブランチのままtest1.pyに以下の内容を追加した。

test1.py
# 最初のコミット
print("test1")

# 内容の追加
print("test2")

保存をすると画像みたいにunstagedの箇所にtest1.pyの変更が反映される。

次にこの追加した内容を違うブランチに反映したい。
同じブランチでそのままコミットすることも可能ですが、基本的に相手に確認してもらっている最中にコミットするのはあまり気持ちのいいものではないので避けたい。今回の例は追加のみでしたが実際は手順①でプルリクしている箇所の間違いに気づいて修正することも考えられます。(相手からすると途中までみてたのに勝手に内容変えられると最初から見ないといけないじゃないかクソが!となってしまします。笑)
 

手順③test1.pyに追加した内容をgit stash listに避難させる

変更内容を避難させる。
ターミナル(windowsの場合はコマンドプロンプト)にてgit stashコマンドを実行します。するとAブランチにあるtest1.pyファイルは以下のようになります。

ターミナル
git stash

<実行後>

test1.py
# 最初のコミット
print("test1")

手順①でコミットした時のファイルの内容に戻ります。言い方を変えると手順②で追加した内容をgit stash listに避難させています。unstagedの箇所にあったtest1.pyの変更もなくなります。(以下の画像のようになります。)

手順④git stash list を確認するコマンドの確認

避難させたgit stash listを確認する。使用するコマンドは以下のとおりです。

git stash list

(内容)
git stash listを確認できます。
(使用例)

ターミナル
git stash list

<以下実行結果>
stash@{0}: WIP on branch_name: commit_id2 commit_comment2

上のstash@{0}に先ほど避難させた内容が入っています。この0はstash listの0番目だよってことを示しています。複数ある場合はこの数字によって使用したいstash listを指定します。実行しても何も起きない場合はgit stash list がないことを示します。
※git stash listにsatsh@{0}があるときにgit stash listコマンドを実行すると実行前のstash@{0}はstash@{1}となる。新たにstashされた内容がstash@{0}となる。{}の中の数字が小さいほど新しいstash listの内容である。

git stash show stash@{0} -p

(内容)
git stash list の退避内容が確認できます。stash@{0}の中の0はgit stash list が複数ある際にどのstash listを確認したいかを指定するものです。-pの部分は--patchでも代用可能です。

(使用例)

ターミナル
git stash show stash@{0} -p

<以下実行結果>
# 最初のコミット
print("test1")
+
+# 内容の追加
+print("test2")

git diff stash@{0}

(内容)git stash list のdiff(差分)を表示できます。言葉での説明はわかりにくいので使用例をみてください。

(使用例)

ターミナル
git diff stash@{0}

<以下実行結果>
# 最初のコミット
print("test1")
-
-# 内容の追加
-print("test2")

手順⑤新しいブランチを作成(Bブランチ作成)

反映をさせる前に新しいブランチを作ります。ここではmasterブランチからBブランチを作ります。

手順⑥リモートの内容をBブランチにpullする(Aブランチの状態によってpullしてくる箇所が異なる)

Bブランチ作成後に、リモートの内容をpullするのですが、Aブランチのプルリクがマージされているのか、されていないのかでpullしてくる箇所が変わってきます。

1.マージされている場合

git pull origin masterによりリモートのmasterブランチの内容をBブランチに反映させる。その時のtest1.pyの内容は以下のとおりである。

test1.py
# 最初のコミット
print("test1")

2.マージされていない場合
git pull origin Aによりプルリク中のAブランチの内容を反映させる。これでもtest1.pyのAブランチの内容をBブランチに反映させることができる。反映内容は上記と同様。

test1.py
# 最初のコミット
print("test1")

※注意

2の方法によりpullしてきた箇所を修正すると、AブランチのプルリクがマージされたあとBブランチのプルリクをマージしようとするとコンフリクトしてしまいます。コンフリクトしても都度解消すれば特に問題はありません。
pullしてきた箇所を修正せず追加のみだとコンフリクトはおきません。

(補足)Aブランチの内容をBブランチにpullしたいときにAブランチに複数のコミットがあり、その中の1つの内容を反映させたい場合があると思います。その時はgit cherry-pickという便利なコマンドがあります。cherry-pickについて知りたい方は以下のurlでわかりやすく説明されている方がおられますのでそちらを参考にしてください。

[git]他ブランチの作業を自分のブランチに持ってくる方法まとめ

手順⑦git stash listの内容を反映することができるコマンドを確認

反映ができるコマンドは主に2つあります。

○1つ目

git stash apply stash@{0}

こっちは反映した後にgit stash listはそのまま残ります。

○2つ目

git stash pop stash@{0}

こっちは反映した後にgit stash list を削除されます。

{}の中の数字は整数を入れてどのstash listの内容を反映するのかを指定します。
stash listを指定しない場合は、デフォルトでstash@{0}指定されます。

手順⑧git stash listの内容を反映する

手順⑦で確認したgit stash popコマンドにより避難させた内容を以下のとおり反映します。

ターミナル
git stash pop stash@{0}

実行後のtest1.pyファイル

test1.py
# 最初のコミット
print("test1")

# 内容の追加
print("test2")

これで手順①でプルリク後からの変更内容をBブランチに反映することができました。
このあとにgit stash listを実行してもstash@{0}はありません。git stash apply stash@{0}により実行した場合だとstash@{0}は残っています。

参照url