##概要
revert, reset, 両者の違いについて , ついでにclean
##git revert
<commit>
によって加えられたすべての変更を元に戻す新しいコミットを生成し、現在のブランチに適用する。
git revert <commit>
##ユースケース
バグの追跡を行った結果、あるひとつのコミットが原因だった!そのコミットをプロジェクト履歴から取り除きたい。という時に。
##打ち消しと取り消し
git revertは 指定したコミットを元に戻して新しいコミットにする
であり、指定したコミットを取り消して過去の状態に戻る
は 後述の git reset
である。
##打ち消しの利点
取り消しと比較すると2つの重要な利点がある。
###1.プロジェクトの履歴が変更されない
git resetで公開した変更履歴を改変することについての危険性を説明するが、git revertは履歴が残るので公開されているコミットに対して安全
な操作となる。
###2.任意のコミットを指定しやすい
git resetで任意のコミットを指定すると、後に行われた全ての作業を再びコミットしなければならない点に対し、git revert ならその必要がない。
##使用例
あるスナップショットをコミット、その後 それをrevertする。
#とあるファイルを編集したのでコミット
% git commit -m 'ファイルを編集'
# コミットを打ち消し
% git revert HEAD
上記を図にする。四番目のコミットを打ち消して新しいコミットが追加されていることがわかる。履歴には残っているので打ち消したコミットにcheckoutで戻ることもできる。
##git reset
git revert
が履歴を残す 安全
な方法に対し、git reset
はコミットを取り消して過去の状態に戻るので、resetを取り消すことができないので危険
な方法であると言える。
##ユースケース
変更のアンステージや、一連のスナップショットのコミット取り消しを行ってリポジトリを整理して再構築したいとき。
--hardフラグをつけるときは 開発中の実験的作業の結果が思わしくなかったので全くなかったことにしたい、そんな時。
このコマンドはローカルな変更を元に戻したいときに限るべきである、他の開発者に公開されているコミットの取り消しは決して行わないように。
##コマンド例
指定したファイルをステージングから削除する
git reset <file>
ステージングをリセットして直前のコミット状態と一致させる
git reset
ステージングと作業ディレクトリをリセットして直前のコミット状態と一致させる。ローカルの作業も破棄されるので注意して使用する。
git reset --hard
現在のブランチの先端を<commit>
の位置に戻し、ステージングをその状態と一致するように戻す。作業内容は維持する。<commit>
の後の改変内容は作業ディレクトリに保持されている。
git reset <commit>
現在のブランチの先端を<commit>
の位置に戻し、ステージングと作業ディレクトリを同じ状態にする。
<commit>
の後に行われたすべてのコミットはなかったことになる。
git reset --hard <commit>
##公開済みの履歴取り消しはダメ、絶対。
<commit>
の実行後にpushを行ったらgit reset <commit>
は絶対に使用してはならない。すでに公開されているので、他の開発者がそれを前提として作業を行っている可能性があるから。
公開済みの履歴をreset すると以下のようなことが発生する。
reset した後に 新規コミットが行われると Gitではローカルな履歴が origin/master から分岐した
と扱われてしまう (After Committingの図の箇所)
git reset をはローカルの実験作業を取り消すのが目的。
公開済みのコミットを訂正する必要がある場合は git revert
を使う。
##使用例
git reset を使用して関連性のないファイルをアンステージしてコミットの目的を明確にする。
# リポジトリに追加されている hello.pyとmain.pyを編集 して add
git add .
# main.pyとhello.pyの関連性がほとんどなかったので一方をアンステージする
git reset main.py
# hello.pyのみステージングに上がっているのでコミットする
git commit -m 'hello.pyを修正'
# つづいてmain.pyをaddしてコミット
git add main.py
git commit -m 'main.pyを修正'
###ローカルなコミットの削除
ローカルレポジトリで実験的な開発を行っている状態。いくつかのスナップショットをコミットとしているが、それらをすべて破棄したい。
# 新しいファイルを追加してコミット
git add foo.py
git commit -m 'Start developint crazy feature'
# foo.py 、他いくつかのファイルを編集してコミット
git commit -a -m 'Conitune my crazy feature'
# 今までの実験的な作業を全部やめて関連コミットを全部消したいと考えた
# コミット二回分だけ前に戻す (2つのスナップショットを履歴から削除する)
git reset --hard HEAD~2
作業ディレクトリから追跡対象外のファイルを削除する。
git clean
は rm
同様に元に戻すことができないので注意する。
git reset --hard
を使って作業ディレクトリをある特定のコミットの時点と完全に同一の状態にしたいときに併用する。
resetコマンドが作用するのは追跡対象になっているファイルのみなので、cleanコマンドをつかって追跡対象外のファイルも削除して 同一コミットの状態にする。
git clean の予行演習をする。実際に削除はされない。
git clean -n
追跡対象外のファイルをカレントディレクトリから削除する。.gitignoreで指定されているものは削除しない。
git clean -f
指定パスの追跡対象外ファイルを削除する
git clean -f <path>
カレントの追跡対象外ファイルとディレクトリを削除する
git clean -df
カレントの追跡対象外ファイルと通常無視されるファイルを削除する
git clean -xf
##補足
git clean はビルド完了後のコンパイラが制せした.o や .exeなどのファイルを簡単に削除できる。リリースする際に必須な作業になる場合がある。このときに git clean -xf
が使える。
git resetとともにコミットの内容を完全に削除してしまうコマンドなので
-f
のオプションを必須にするためエイリアスを作った方がいいかも。
##使用例
実験的な開発をしている状態。いくつかコミットを行っている。作成された新規ファイルを含めて作業ディレクトリ内の変更をすべて取り消したい。
# ファイルを編集している
# 新規ファイルをいくつか追加している
# 全部取り消したい
git reset --hard
# 追跡対象外のファイルも削除 (ステージングには上がっていないファイル)
git clean -df
上記を行うと作業ディレクトリとステージングは直前のコミットと全く同一の状態になる。 git status を実行するとクリーンなことがわかる。