Edited at

[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]:ファイルの変更履歴を記録(みんなで共有)


  • add:「ワーキングツリー → インデックス」への反映

  • commit:「インデックス → ローカルリポジトリ」への反映

  • push:「ローカルリポジトリ → リモートリポジトリ」への反映


2. git resetを使いこなす

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

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

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



  • --hard:「HEADの位置・インデックス・ワーキングツリー」全て


  • --mixed(or オプション無し):「HEADの位置・インデックス」


  • --soft:「HEADの位置」のみ

現在のファイルの状態をYとする。


  • ファイルを変更したらワーキングツリーが変更

  • addしたらインデックスが変更

  • commitしたらHEAD( = 最新のコミットのハッシュ値のエイリアス)が1つ前に進む



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



  • reset --hard:全部Yに戻す。


  • reset --mixedcommitaddの取り消し。


  • reset --softcommitのみ取り消し。


★主な利用シーン★


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

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/