Help us understand the problem. What is going on with this article?

[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法

More than 3 years have passed since last update.

1. gitの基礎(言葉の意味)

  • ワーキングツリー[working tree]:最新のファイルの状態
  • インデックス[index](ステージ[stage]):コミットするためのファイルの状態
  • ローカルリポジトリ[local repository]:ファイルの変更履歴を記録(手元で管理)
    • ヘッド[HEAD]:最新のコミットの状態
  • リモートリポジトリ[remote repository]:ファイルの変更履歴を記録(みんなで共有)

2015_0307commit図_2.jpg

  • add:「ワーキングツリー → インデックス」への反映
  • commit:「インデックス → ローカルリポジトリ」への反映
  • push:「ローカルリポジトリ → リモートリポジトリ」への反映

2. git resetを使いこなす

git resetには--hard--mixed--softの3つのオプションがある。

※厳密にはもっとあります。詳しくは`git reset -h`を叩くなどして見てください。

それぞれのオプションにおいて、修正の及ぶ範囲は下記。

  • --hard:「HEADの位置・インデックス・ワーキングツリー」全て
  • --mixed(or オプション無し):「HEADの位置・インデックス」
  • --soft:「HEADの位置」のみ

現在のファイルの状態をYとする。
2015_0307git_reset_1_.jpg

  • ファイルを変更したらワーキングツリーが変更
  • addしたらインデックスが変更
  • commitしたらHEAD( = 最新のコミットのハッシュ値のエイリアス)が1つ前に進む

2015_0307git_reset_2_.jpg
変更をコミットしてファイルの状態がZに移ったとする。
2015_0307git_reset_3_.jpg

  • reset --hard:全部Yに戻す。
  • reset --mixedcommitaddの取り消し。
  • reset --softcommitのみ取り消し。

2015_0307git_reset_4_.jpg

★主な利用シーン★

① 直前のコミットを取り消したい(コミットのみ取り消し)

git reset --soft HEAD^
  • HEAD^:直前のコミットを意味する。
    • @^HEAD~も同じ意味。
    • HEAD~{n} :n個前のコミットを意味する。
    • HEAD^HEAD~{n}の代わりにコミットのハッシュ値を書いても良い。
    • gitのv1.8.5からは、「HEAD」のエイリアスとして「」が用意されている。
    • HEAD^^^HEAD~3HEAD~~~HEAD~{3}@^^^は同じ意味。
  • --softなので、インデックス・ワーキングツリーはそのまま。
  • 上書きコミットしたいなら、git commit --amendを使うとラク!

② 直前のコミットを取り消したい(マルっと消したい)

git reset --hard HEAD^
  • --hardなので、「インデックス・ワーキングツリー」も1つ前のコミットの状態に戻る。

③ コミット後の変更を全部消したい

git reset --hard HEAD
  • --hardなので、「HEADの位置・インデックス・ワーキングツリー」を全てHEADの位置に動かす。
    • HEADの位置はそのまま。
    • 「インデックス・ワーキングツリー」の変更が消せる。

④ addを取り消したい

git reset --mixed HEAD

または、

git reset HEAD
  • --mixed(or オプション無し)なので、「HEADの位置・インデックス」をHEADの位置に動かす。
    • HEADの位置はそのまま。
    • 従って、インデックスの変更(addした内容)のみ元に戻す。

⑤ すごい昔の状態で動作を確認したい

git reset --hard 昔のコミットのハッシュ値
  • これをやる前に、pushして置くことを強くオススメします!
  • reset --hardは基本的にすべて消えるので慎重に。
    • 一応復活させる術はなくはない。
  • remoteに最新の状態を記録しておけば、ローカルは好きな所に移動しても安心。
  • コミットのハッシュ値はgit logで確認すればOK!

動作確認後、最新の状態に戻るには、また、

git reset --hard ORIG_HEAD

をすれば良い。

  • git reset --hard ORIG_HEAD:直前のresetをなかったことにするおまじない!
  • git resetは未来の状態にも行ける。
  • git reset --hard 最新のコミットのハッシュ値でも良い。
  • git rebase origin/masterでも良い。
  • reset --hardrebaseする時は、こまめにソースツリーの状態を確認しておくといいと思います。

3. 間違えてgit resetしちゃったら・・・

直前のリセットを取り消したいなら、

git reset --hard ORIG_HEAD

をすればOK!

reset後色々いじってしまっていたら、慌てずに、git reflogコマンドを叩きましょう。

  • git log:コミットの履歴を見る
  • git reflog:これまでHEADが辿ってきた履歴を見る

git reflogで戻したい状態を見つけ出し、

git reset [(必要なら)オプション] [ハッシュ値]

をすれば良い。
resetで困ったときは「resetreflog」と覚えておこう!

(注) reflogは万能ではない

git reflogは、「これまでHEADが辿ってきた履歴」を保持しているものです。
addしただけでcommitしてないものがある時に、reset --hardをしてしまったら、addした内容は復元不可能です。
addすらしてないものももちろん消えます。

  • git resetを使うときはくれぐれも慎重に!

4. おまけ(gitを使いやすくする)

① ローカルの変更内容を一時的に退避させる。

git stash

退避させた内容を元に戻すには、下記を叩けばOK!

git stash pop

② aliasを作成

gitのaliasは~/.gitconfigに書き込むことが可能。

vim ~/.gitconfig
~/.gitconfig
[alias]
    ad = add
    br = branch
    ci = commit
    co = checkout
    ft = fetch
    pl = pull
    ps = push
    sh = show
    st = status

ただ、個人的にはgitを打つのも面倒なので~/.bashrcにgit系のaliasも書いている。

vim ~/.bashrc
~/.bashrc
# git
alias g='git'
alias gb='git branch'
alias gs='git status'
alias gd='git diff'
alias gds='git diff --staged'
alias ga.='git add .'
alias gcm='git commit -m'
alias gcam='git commit -am'
alias gpod='git push origin develop'
alias gp='git push'
alias gfo='git fetch origin'
alias grod='git rebase origin/develop'
alias gsp='git stash pop'
alias gsu='git submodule update --init --recursive'
alias gcd='git checkout develop'
alias gmnf='git merge --no-ff'

masterを直接いじることをせずdevelopブランチ切ることが多いため、上のようなaliasにしている。
あと、運用方法の好みとして、pullせずrebaseする風潮が自分のまわりであるので、gppushの意味も持たせてしまっている。

③ その他

▼git rebase 失敗した時の対処法
http://qiita.com/shuntaro_tamura/items/c505b76c1021a35ca9ff

▼Gitで補完機能を有効にする方法
http://qiita.com/shuntaro_tamura/items/9ed9321e64dc208fe95a

▼ファイルの変更履歴を行単位(orコミット単位)で調べる方法
http://qiita.com/shuntaro_tamura/items/b8b99a9b4987144581e9

▼コミットの取り消し、打ち消し、上書き
http://qiita.com/shuntaro_tamura/items/06281261d893acf049ed

▼ブランチ切って更新してマージするまでの流れ
http://qiita.com/shuntaro_tamura/items/6c8bf792087fe5dc5103

▼初心者のためのgitコマンド
http://qiita.com/shuntaro_tamura/items/5228a29082a844d4875c

▼【Gitおすすめサイト1】サルでもわかるGit入門
http://www.backlog.jp/git-guide/

▼【Gitおすすめサイト2】Git公式ドキュメント
http://git-scm.com/docs/

sirok
プッシュ通知サービス Growth Pushやその他 グロースハックツールを開発・運営するスタートアップ
http://sirok.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした