revertコマンドの使い方
git revert
commitによって加えられたすべての変更を元に戻す新しいコミットを生成し、現在のブランチに適用する。
git revert <commit>
ユースケース
バグの追跡を行った結果、あるひとつのコミットが原因だった!そのコミットをプロジェクト履歴から取り除きたい。という時に。
打ち消しと取り消し
git revertは「指定したコミットを元に戻して新しいコミットにする」であり、「指定したコミットを取り消して過去の状態に戻る」は後述のgit resetである。
打ち消しの利点
取り消しと比較すると2つの重要な利点がある。
- プロジェクトの履歴が変更されない
- 任意のコミットを指定しやすい
git resetで公開した変更履歴を改変することについての危険性を説明するが、git revertは履歴が残るので公開されているコミットに対して安全な操作となる。
git resetで任意のコミットを指定すると、後に行われた全ての作業を再びコミットしなければならない点に対し、git revertならその必要がない。
使用例
あるスナップショットをコミット、その後それをrevertする。
#とあるファイルを編集したのでコミット
%git commit -m 'ファイルを編集'
#コミットを打ち消し
%git revert HEAD
resetコマンドの使い方
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から分岐したと扱われてしまう。
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
revertコマンドの使い方
git clean
作業ディレクトリから追跡対象外のファイルを削除する。
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を実行するとクリーンなことがわかる。