派遣で働くエンジニアのスキルアップを応援するサイト

PRODUCED BY RECRUIT

【連載】マンガでわかるGit ~コマンド編~ 第6話 git reset 3種類をどこよりもわかりやすい図解で解説!

f:id:itstaffing:20191118140711j:plain

Webサービスやアプリ開発の現場では必須のバージョン管理システム「Git(ギット)」。Gitは、専用のソフトを使えばクリックで直感的に操作することもできますが、いざというときにコマンドが使えると便利です。

前回の 第5話 では、特定のコミットを打ち消すコマンド「リバート」を学びました。

・特定のコミットを打ち消す

& git revert [打ち消したいコミットID]

今回の第6話では、特定の時点までファイルを巻き戻す「リセット」を学びます。このリセットには3種類方法があります。git reset --soft、--mixed、--hardです。「これらは何が違うのか?どのように使い分ければいいのか?」初心者の方は困ってしまいますよね。このマンガを通して、わかばちゃんと一緒に理解していきましょう!

【筆者】湊川 あいさん
【筆者】湊川 あいさん
フリーランスのWebデザイナー・漫画家・イラストレーター。マンガと図解で、技術をわかりやすく伝えることが好き。 著書『わかばちゃんと学ぶGit使い方入門』・『わかばちゃんと学ぶ Googleアナリティクス』・『わかばちゃんと学ぶ Webサイト制作の基本』『運用ちゃんと学ぶ』が発売中のほか、マンガでわかるGit・マンガでわかるDocker・マンガでわかるRuby・マンガでわかるScrapbox・マンガでわかるLINE Clova開発・マンガでわかる衛星データ活用といった分野横断的なコンテンツを展開している。

・Amazon著者ページ
・Twitterアカウント

リセットには3種類ある

f:id:itstaffing:20191118140646j:plain
f:id:itstaffing:20191118140649j:plain
f:id:itstaffing:20190617145541j:plain
第1話で出てきた、この図は覚えているかな?
f:id:itstaffing:20190617145538j:plain
うん、覚えてるよ。
f:id:itstaffing:20190617145541j:plain
リセットはこの状態を頭に思い描けばそう難しくはないんだ。3種類のオプションそれぞれが影響を与える範囲は次のとおりだ。
--soft:HEADの位置のみ
--mixed:HEADの位置・ステージ
--hard:HEADの位置・ステージ・作業ディレクトリ

f:id:itstaffing:20190617145538j:plain
強度が上がるたびに影響を与える範囲が広くなってるね。ところでHEAD(ヘッド)って何?
f:id:itstaffing:20190617145541j:plain
HEADというのは、簡単に言えば「自分が今いる位置」のことだ。たいていはブランチの先頭のコミットを指していることが多い。こいつを過去のコミットに移動させることで、ブランチを過去に巻き戻すわけだが、そのときにステージも道連れにするのがmixed。ステージも作業ディレクトリも道連れにするのがhardだ。

git reset --soft

f:id:itstaffing:20191118140652j:plain
f:id:itstaffing:20190617145541j:plain
--soft は resetの中でも最弱。HEADだけを動かす、一番弱いオプションだ。

「直前のコミット内容を修正したい」「コミットし直したい」というときに便利なのがこのコマンドです。

--soft 活用例:直前のコミット内容を修正したい

$ git reset --soft HEAD^


例えば「まだ作業をしようと思っていたのに間違えてコミットしてしまった」「2つのファイルをまとめてコミットするべきだったのに、間違えて1つしかコミットしていなかった」などです。このコマンドを実行すると、まさに「コミットをする直前」の状態に戻ります。

▼ git reset --soft 実行後の状態

f:id:itstaffing:20191118140654j:plain

f:id:itstaffing:20190617145538j:plain
ふむふむ。コミットされていたファイルがステージに上がっているね。まさに「コミット」という動作だけを取り消した感じだね。
★魔王教授のコラム

上のコマンドの中にあった「HEAD^」というのは、「1つ前のコミット」という意味だ。では「2つ前のコミット」を表すにはどう打つか分かるかな?

答えは簡単「HEAD^^」だ。

では、8個前のコミットまで巻き戻すときはどうする?もちろん「HEAD^^^^^^^^」と書くこともできるが、指が疲れるし間違えそうだ。そこで「HEAD~8」のように書くこともできる。

え?8個前だと数えるのも面倒だって?もちろんコミットIDで指定することもできるぞ。たとえば次のように打てる。

$ git reset --soft caddd1c


git reset --mixed

f:id:itstaffing:20191118140657j:plain
f:id:itstaffing:20190617145541j:plain
--mixedは中程度の効果。HEADと一緒にステージも道連れにして巻き戻す。作業ディレクトリのファイルは消えないから安心してくれ。

「いくつかgit addでステージしたけど、やっぱやめた」というときに使えるコマンドです。作業ディレクトリのファイルは消えないので安心です。

--mixed 活用例:ステージしたものを取り消したい

$ git reset --mixed HEAD


ちなみに、オプション無しでも--mixedを実行したときと同じ結果が得られます。よって、次のように短く書くこともできます。

$ git reset HEAD

git reset --hard

f:id:itstaffing:20191118140701j:plain
f:id:itstaffing:20190617145541j:plain
--hard は一番強力なオプションだから取扱注意だ。HEADと一緒にステージだけでなく作業ディレクトリも道連れにして巻き戻してしまう。

「ステージングエリアにも作業ディレクトリにも残らなくていいから、コミットをまるごと消したい」というときに使えるコマンドです。

--hard 活用例:ひとつ前のコミットまでまるごと消したい

$ git reset --hard HEAD^


もちろんコミットIDを指定することもできます。指定した時点まで「HEAD・ステージングエリア・作業ディレクトリ」のすべてが巻き戻されます。

例として、極端ですが、この練習用リポジトリのmasterブランチのチェックアウトした状態で「はじめてのコミット」に戻ってみるとしましょう。

f:id:itstaffing:20191118140704j:plain

$ git reset --hard 02f11b7

実行すると、

f:id:itstaffing:20191118140706j:plain

masterブランチが「はじめてのコミット」に巻き戻りました。newsブランチとdevelopブランチは巻き戻らず、そのままですね。なぜだかわかりますか?

あくまでもHEADは「今自分がいるブランチの先頭」を指すものですから、masterブランチだけが巻き戻り、newsブランチとdevelopブランチはリセットの影響を受けなかったというわけです。

ここからさらに新しいコミットを乗せることもできますが、それをリモートリポジトリにプッシュすると他の人のmasterブランチにも影響が出てしまいます。「リセットは危ない」と言われるのはこのためです。git reset --hardを使う場合は、プッシュ前のコミットに対してのみ、使うようにしましょう。

f:id:itstaffing:20190617145538j:plain
リセット3種類、何がどう違うかわかったよ!
f:id:itstaffing:20190617145541j:plain
最初は難しく感じるかもしれないが、少しずつ慣れていくといいぞ。リセットの自信がないときや、プッシュ済みのコミットを打ち消したいときは、この前教えたリバートを使っておけばいい。
f:id:itstaffing:20190617145538j:plain
はい!ところで、最後のgit reset --hardの練習で、今までのコミット履歴ががっつり消えちゃったんですけどそれは……?
f:id:itstaffing:20190617145541j:plain
HAHAHA!そんなこともあろうかと思って、用意しておいたコマンドがある!間違えてリセットしても、git reflog(リフログ)で元どおりだ!次の授業をお楽しみに。

まとめ

ここまでで3種類のリセットの特徴がわかりました。

・特定の時点までファイルを巻き戻す

$ git reset --soft [巻き戻したい時点のコミットを指定]

f:id:itstaffing:20191118140652j:plain

$ git reset --mixed [巻き戻したい時点のコミットを指定]

f:id:itstaffing:20191118140657j:plain

$ git reset --hard [巻き戻したい時点のコミットを指定]

f:id:itstaffing:20191118140701j:plain

Gitにはまだまだたくさんのコマンドがあります。
次回、第7話では、いざというときに便利な git reflog(リフログ)について学んでいきましょう。

▼ これまでの「マンガでわかるGit」