gitでさっきのコミットを取り消して、変更したい時がありますよね。その実演を初心者向けにログとして残しておきます。今回は、gistを使いましたが長いログを残すのには便利かなと思いました。gistを整理できるGistBoxというのがあるのですが、タグ機能は公式でつけて欲しいです。
# zshにて確認。
# 前回のコミットを取り消す方法を試します。
# gitリポジトリを作成します。
% git init
# ファイルa,b,c.txtを作り別々にコミットします。
% touch a.txt
% git add .
% git commit -m "first"
% touch b.txt
% git add .
% touch c.txt
% git add .
% git commit -m "add c.txt"
% git commit -m "add b.txt"
# 3回のコミットに分かれていることを確認します。
% git log --oneline
77b5e50 add c.txt
1bc5988 add b.txt
6067116 first
# softは編集結果を削除しない、コミットの取り消しです。
% git reset --soft HEAD
# HEADを指定した場合は何も発生しませんね。
% git log --oneline
77b5e50 add c.txt
1bc5988 add b.txt
6067116 first
# 現在、ステージングエリアに何もないことを確認して次の実験をしていきます。
% git status
On branch master
nothing to commit, working directory clean
# d.txtを作成した直後は、まだトラッキング(監視)されていません。
# つまりgitの管理対象にd.txtは含まれていないということです。
% touch d.txt
% git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
d.txt
nothing added to commit but untracked files present (use "git add" to track)
# もう一度soft resetしますが、何も置きません。
% git reset --soft HEAD
% git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
d.txt
nothing added to commit but untracked files present (use "git add" to track)
# 今度はd.txtをステージングエリアにあげてから試します。
% git add d.txt
% git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: d.txt
% git reset --soft HEAD
% git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: d.txt
# 何も変わりはありませんでした。
# ステージングエリアにあげたファイルを、取り消すことをアンステージといいますが、
# その方法は上記のgit statusのログに記述されていますね。
# > use "git reset HEAD <file>..." to unstage
# softオプションをつけるとエラーになってしまいます。
% git reset --soft HEAD d.txt
fatal: Cannot do soft reset with paths.
# softを外してみましょう。アンステージされましたね。
% git reset HEAD d.txt
% git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
d.txt
nothing added to commit but untracked files present (use "git add" to track)
# ちなみにHEADは省略できます。次の通りでもOKです。
# git reset d.txt
# 全てのファイルを一括でアンステージする場合は「.」を指定すればいいです。
# git reset .
# HEADとは現在の作業場所を指しています。なので、HEADだけだとステージングエリアが対象になるわけです。
# 次は、本題のコミットの取り消しを行います。
# まずhard resetで前回のコミットの状態まで戻します。
# softと違い、編集内容を全て削除します。
# ただし、先にトラッキングして置かないといけないのでaddします。
# リセットの対象はaddされたものです。
% git add .
% git reset --hard
HEAD is now at 77b5e50 add c.txt
% git log --oneline
77b5e50 add c.txt
1bc5988 add b.txt
6067116 first
# では最初のコミットfirstまで戻ってみます。
# HEADに^(ハット)をつけるとその数だけ前のコミットを指します。
# 今回は2つつけるので「b.txt」を指します。
% git reset --soft HEAD^^
% git log --oneline
6067116 first
# firstまで戻っていますね。
# 先ほどのresetコマンドは「add b.txt」までのコミットを取り消すという意味でした。
# hardではなksoftなので、編集内容は削除されていません。
% git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: b.txt
new file: c.txt
# 今度はb,c.txtを一緒にコミットしたりすることができます。