2014/02/04更新

[git] 変更を取り消す

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
今日は、gitで開発していて「あっちょっと元に戻したいな」という時の手順をブログに書きたいと思います。

画像

引用:http://flic.kr/p/6zJjzs




作業の変更を取り消す

gitを使って開発している場合に、作業前に戻したいなっていうことありませんか? そんな時に行うことができる変更取り消しの手順を説明します。
変更取り消しの手順は、以下3つの段階別に対応する必要があります。

  1. add前の変更を取り消す
  2. addしたけどcommitしていない変更を取り消す
  3. commitを取り消す

それでは、それぞれの状態別に取り消す方法を見ていきましょう。



add前の変更を取り消す

pullしてきたあとに、変更したものの、やっぱりもとの状態に戻したいという場合のリセット方法です。 ここでは、addもcommitもしていないファイルが対象です。
取り消し方法には、以下のように行います。
# 特定のファイルの変更を取り消す
$ git checkout <ファイル名>

#特定のディレクトリ以下の変更を再起的に取り消す
$git checkout <ディレクトリ名>

# 全てを元に戻す
$ git checkout .
これで、編集したファイルを自由にHEADリビジョンまで戻せるようになりました。 ちなみに、git statusをした場合に、ちゃんと取り消し方も表示されています。gitは親切ですね。
$ git st
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   aaa.txt
#
no changes added to commit (use "git add" and/or "git commit -a")



addしたけどcommitしていない変更を取り消す

続いてaddを取り消す方法です。 間違えてaddしちゃったとか、gitigonre設定する前に追加しちゃったとか、addを取り消したいことも時々あるでしょう。 以下のように行います。
$ git reset HEAD <ファイル名>
これでaddだけ取り消されました。ファイルシステム上の変更はそのままなので、それも戻すには1つ上で紹介した内容を行います。
これの方法も、ちゃんとgit statusで説明されていますね。add取り消しのやり方を忘れたとしても、git statusで確認できるのはありがたいです。
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   aaa.txt
#



commitを取り消す

最後にcommitの取り消しです。gitコマンドをノリノリで使っていたら不要なものもcommitしちゃったとか、コミットメッセージが間違えちゃったとか時々あります。この場合には、以下のように取り消します。

commit取り消しについては、「直前のcommitをやり直す」と「コミットを取り消す」の2パターンに分けて説明したいと思います。


直前のcommitをやり直す

commitを取り消す場合に、直前のcommitをやり直すということで直前のcommitを無効化することができます。
例えば今回の場合、aaa.txtの変更をcommitし忘れた場合を考えてみましょう。commit直前の状態は以下とします。
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   bbb.txt  # コミット対象
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   aaa.txt  # addしてないからコミット対象じゃない
#
aaa.txtをaddし忘れていているという状況です。
ここでコミットすると以下のようになります。
# commitする
$ git commit -m "革新的な実装ができた!"
[master b682426] 革新的な実装ができた!
 1 file changed, 4 insertions(+)

# statusを確認する
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.  # コミットされた
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   aaa.txt  # あっ、、commitから漏れてる。。
#
no changes added to commit (use "git add" and/or "git commit -a")
あちゃ、commitは無事にできましたが、aaa.txtをcommitに含め忘れていますね。ここでlogを確認すると以下のようになります。
$ git log -1
commit b6824266627379ea922189a78a9cfc3f4a778382  # [1]
Author: munesada_yohei <y.munesada@gmail.com>
Date:   Fri Jan 31 15:39:30 2014 +0900

    革新的な実装ができた!
上記の[1]というログが、今回やり直したい対象です。

まずは、先ほどのコミットに入れ忘れたファイルを追加して、commit対象(=staged状態)にします。
$ git add aaa.txt
そして、直前のコミットをやり直します。やり直すには以下のように行います。
$ git commit --amend
そうするとコミットコメントの修正も促されます(ターミナルでgitを使っている場合には、vimなどが立ち上がります)。 コメントの修正が終わるとコミットが行われ、結果として以下のように出力されます。
[master 862ea1e] 革新的な実装ができた!ファイルも忘れず追加!
 2 files changed, 7 insertions(+)
変更対象ファイルが1fileから2filesに変わってますね。ログを確認してみましょう。
$ git log -2
commit 862ea1e9d3541c751183f0c546a646fb5ca702cd
Author: munesada_yohei <y.munesada@gmail.com>
Date:   Fri Jan 31 15:39:30 2014 +0900

    革新的な実装ができた!ファイルも忘れず追加!

commit 485b4a7170ef5d5639ca3a6fa198b1a31cc135fe
Author: munesada_yohei <y.munesada@gmail.com>
Date:   Fri Jan 31 15:17:26 2014 +0900

    add for test
2つ分のログが出力されました。コミットをやり直した結果、やり直す前のコミット(ハッシュ値:b682426)は表示されていないですね。 無事にコミットのやり直しができました。



commitを取り消す

続いてcommitを取り消します。直前の以下のコミットを取り消したいとします。
$ git log --stat -1
commit 686ed5948a5ec2fdc493afaef2fd70b567f4462c
Author: munesada_yohei <munesada_yohei@cyberagent.co.jp>
Date:   Fri Jan 31 15:51:18 2014 +0900

    取り消したいコミットを作った

 aaa.txt | 2 ++
 1 file changed, 2 insertions(+)
aaa.txtを変更してコミットしたという状況です。取り消すには、以下2つの方法があります。
# git上での変更のみ取り消し、ファイルシステム上のファイルはそのまま
$ git reset --soft HEAD^

# git上での変更取り消しと、ファイルシステム上でのファイル変更も取り消し
$ git reset --hard HEAD^
ここで「HEAD^」は、HEADリビジョンの1つ前まで取り消すという意味です。 特定のリビジョンまで戻すには、そのリビジョンのハッシュタグを指定します。
$ git log -3 --pretty=oneline
862ea1e9d3541c751183f0c546a646fb5ca702cd 革新的な実装ができた!ファイルも忘れず追加!
485b4a7170ef5d5639ca3a6fa198b1a31cc135fe add for test
12ac1cf45d87e27d3b606c686fe9bdc9f6174367 add for test2

# 2つ前まで戻す
$ git reset --hard 12ac1cf45d87e27d3b606c686fe9bdc9f6174367
ただし、すでにリモートにpushしてるcommitは取り消さない方が良いですね。他の人と共同で開発しているなら、てんやわんやです。。むちゃなresetはしないことが大切です。



最後に

今回の内容は以上です。 取り消しせずに実装がスムーズにできるのが一番良いですが、やっぱりそうは言っても、変更を取り消したいときって時々ありますよね。 ぜひそんな時に上のコマンドを使い分けて対応してみてください。

最後までご覧頂きましてありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。