こんにちは、ECF Techブログ
担当のMichiです。
Gitシリーズは8回目を迎えました。「Gitを使いこなそう!」とタイトルを新たにし、実際の開発業務などで役に立ちそうな、ちょっと応用編をお届けしたいと思います。
今回のテーマは「リセット編」。コミットしちゃったけどちょっと失敗したなという時に使えるgit reset
コマンドをご紹介したいと思います。
本記事は、Gitシリーズ連載記事の1つとなっています。もし最初からご覧になりたい方は下のリンクをご活用ください。
対象読者
- Gitの基本的な使い方
pull
、add
、commit
、push
などを使ったことがある方 - gitをもう少しつっこんで学習したいという方
Gitが管理する領域
Gitのやり直し系コマンドは様々です。これらを使いこなすにあたり、Gitが管理する作業領域を理解することは大変重要となります。
Gitの管理領域は次の3つとなります。
作業フォルダ
いわゆるWindows上のフォルダであり、自由な作業場所です。最終コミット以降変更されたファイルやまだGitの管理対象になっていないファイルなどが混在します。
ステージングエリア
インデックスツリーという言い方が正式ですが、本記事では理解しやすいようにこの名前を使っています。git add
コマンドで指定されたファイルがこちらに入ります。次回git commit
の際に、コミット対象となるファイルが管理されています。
リポジトリ
ファイルの最新コミット状態を持っています。
git reset
管理領域の理解ができたところで、git reset
コマンドについて、ハンズオン(実際に動作しながら学習する)形式で見ていきたいと思います。
まずは適当なフォルダでgit init
コマンドを実行しましょう。
C:\work01>git init Initialized empty Git repository in C:/work01/.git/
ファイルを1つ作成します。file.txt
という名前のファイルです。次の内容とします。
A
Aという文字があるだけのファイルです。できたらコミットします。
C:\work01>git add . C:\work01>git commit -m "commit A" [master (root-commit) 34c67d7] commit A 1 file changed, 1 insertion(+) create mode 100644 file.txt
もう1度file.txt
を編集します。内容はつぎのようにします。
B
AがBに変更されただけです。保存したらコミットします。
C:\work01>git add . C:\work01>git commit -m "commit B" [master c5df9cf] commit B 1 file changed, 1 insertion(+), 1 deletion(-)
3つの領域でfile.txtはすべて同じ内容です。ここでgitの状態を確認するgit status
を実行してみましょう。
C:\work01>git status On branch master nothing to commit, working tree clean
masterブランチを指し示していること、コミットすべきものがないことがわかります。
またgit log
コマンドを使って、コミット履歴を確認してみましょう。
C:\work01>git log commit c5df9cf1a0ebd1399e522b795c8717dc2185af71 (HEAD -> master) Author: michiDate: Fri Oct 18 20:15:50 2019 +0900 commit B commit 34c67d71bd2ec0c5eaca9f3872d4871815ba3fd2 Author: michi Date: Fri Oct 18 20:02:55 2019 +0900 commit A
2つのコミットオブジェクトがあり、現在は上のオブジェクトを指していることが分かります。
ではここから、git reset
コマンドを使っていきたいと思います。まずは次のコマンドを実行してください。
git reset --soft HEAD~
コミットへの移動方法
コミットへの移動方法はオプションです。上の例では--soft
ですが、ほかに--mixed
と--hard
があります。省略した場合は自動的に--mixed
が適用されます。
対象コミット
対象コミットの表し方は色々あります。今回使用したHEAD~
はHEADが指すコミットの1つ前のコミットを指します。
3つのオプションを使いこなす
--softオプション
では、コミットへの移動方法について見ていきましょう。--soft
の場合各管理領域は次のようになります。
HEADが移動し1つ前のコミットを指しています。行われた変更はこれだけです。コミットの内容とステージングエリアの内容が異なっているため、git status
コマンドを実行すると、次のように表示されます。
C:\work01>git status On branch master Changes to be committed: (use "git restore --staged..." to unstage) modified: file.txt
ここでコミットをすることでメッセージを変更したりすることができます。再度コミットしておきましょう。
C:\work01>git commit -m "ReCommit B" [master 0802995] ReCommit B 1 file changed, 1 insertion(+), 1 deletion(-)
--mixedオプション
次に--mixedです。git reset --mixed HEAD~
を実行すると各管理領域は次のようになります。
行なわれたことは2つです。
- HEADポインタが1つ前に戻る
- ステージングエリアの内容がHEADが指すコミット内容で置きかわる
よって、git status
コマンドを実行すると・・・・
C:\work01>git status On branch master Changes not staged for commit: (use "git add..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: file.txt no changes added to commit (use "git add" and/or "git commit -a")
git add
コマンドでステージングエリアに上げてから、コミットしましょう。といったメッセージが出ます。
というわけで再度、add
とcommit
をしておきましょう。
C:\work01>git add . C:\work01>git commit -m "mixed Test" [master c9ae784] mixed Test 1 file changed, 1 insertion(+), 1 deletion(-)
--hardオプション
最後に--hardです。git reset --hard HEAD~
を実行すると各管理領域は次のようになります。
行なわれた作業は3つです。
- HEADポインタが1つ前に戻る
- ステージングエリアの内容がHEADが指すコミット内容で置きかわる
- 作業フォルダの内容がHEADが指すコミット内容で置きかわる
3つ目の作業は重要です。なぜなら作業フォルダの変更が消えてしまうからです。今回の例だと「B」という変更はどこを探してもありません。今回は1度コミットしているため復元することができます。しかし作業フォルダにコミットしていないものが含まれていた場合は、戻すことができませんので注意が必要です。
リセットをリセット
--hard
オプションを使用して作業内容「B」が戻せなくなってしまいましたので、コミットした内容から復元しましょう。
まずは戻したいコミットオブジェクトを探します。git reflog
コマンドを実行します。
C:\work01>git reflog c9ae784 (HEAD -> master) HEAD@{0}: commit: mixed Test 34c67d7 HEAD@{1}: reset: moving to HEAD~ 0802995 HEAD@{2}: commit: ReCommit B 34c67d7 HEAD@{3}: reset: moving to HEAD~ c5df9cf HEAD@{4}: reset: moving to HEAD@{1} 34c67d7 HEAD@{5}: reset: moving to HEAD~ c5df9cf HEAD@{6}: commit: commit B 34c67d7 HEAD@{7}: commit (initial): commit A
resetやcommitをくり返した履歴が確認できます。新しい方が上で古い方が下に見えています。今回は下から2番目の「commit B」とコメントしていたコミットに戻ります。コマンドは次です。
git reset --soft HEAD@{6}
実行後はfile.txtが元(「B」と書かれている状態)に戻っていることがわかります。
おわりに
本日はここまでとさせていただきます。最後までご覧くださりありがとうございました。やり直し系のコマンドはまだまだ奥深く紹介しきれていないところもありますが、少しずつお伝えできればと思っています。ぜひ、ひきつづきご覧ください。
合同会社イー・シー・エフでは、子ども向けプログラミングなどの教育講座を実施しています。プログラミング教室の案内や教育教材の情報、また関連するご相談・問い合わせにつきましては下記よりご確認ください。