先日、間違ったファイルをリモートブランチにプッシュしてしまいました。
何とか解決できたので、その時のコマンドの流れを忘れないように残しておこうと思います。
ここで登場する用語
参考記事
ワーキングツリー
- ユーザーが作業しているディレクトリ領域
ステージング
- コミット対象のファイルを登録する領域
-
git add
でステージングできる - インデックスとも言うらしい
HEAD
- 今いるブランチの最新コミット
- HEAD^は1つ前のコミット
間違ったファイルをプッシュした
ここでは、push_test_01.txt
をリモートブランチにプッシュする必要がなかった(もしくはプッシュしてはいけなかった)とします。
$ git add .
$ git status
On branch develop
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: push_test_01.txt
new file: push_test_02.txt
modified: test_01.txt
$ git commit -m "テスト3"
$ git push origin develop
間違えてプッシュしてしまいました。
こんな感じに戻したい
目的はこの2つです。
- テスト3としてコミットする前の状態(テスト2の状態)に戻したい
- けれど、ワークツリーの変更(push_test_01.txt, push_test_02.txt, test_01.txtの変更)はそのまま残したい
ログの確認
git log
でログを確認します。
プッシュを取り消すには、まずコミットを取り消す必要があります。
取り消すと言うより、過去の状態に戻すと言ったほうが正しいかもしれません。
ここでの巻き戻し先は、テスト2です。
$ git log -3
commit コミットID (HEAD -> develop, origin/develop)
Author: author_name <author@example.com>
Date: Sun Dec 9 17:34:33 2018 +0900
テスト3
commit コミットID
Author: author_name <author@example.com>
Date: Sun Nov 18 16:31:46 2018 +0900
テスト2
commit コミットID
Author: author_name <author@example.com>
Date: Sun Nov 18 16:08:16 2018 +0900
テスト1
コミットの巻き戻し
git reset
でコミットを巻き戻すことができます。
コミットIDは、戻したい時点のコミットIDを指定します。
ここではテスト2の状態に戻したいので、テスト2のコミットIDを指定します。
$ git reset --soft テスト2のコミットID
softオプション
を指定すると、ワークツリーの変更とステージングの状態はそのまま残ります。hardオプション
を指定すると、どちらの内容も消えます。
デフォルトはmixedオプション
です。(ワークツリーの変更は残るが、ステージングの状態は戻る。)
コマンド実行後、必ずgit log
でログを確認します。
テスト3のコミットが消えました。
$ git log -3
commit コミットID
Author: author_name <author@example.com>
Date: Sun Nov 18 16:31:46 2018 +0900
テスト2
commit コミットID
Author: author_name <author@example.com>
Date: Sun Nov 18 16:08:16 2018 +0900
テスト1
commit コミットID
Author: author_name <author@example.com>
Date: Sun Nov 18 16:08:16 2018 +0900
テスト0
ワークツリーもそのままです。ファイルを変更した後、ステージングされた状態(git add
後の状態)に戻っています。
$ git status
On branch develop
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: push_test_01.txt
new file: push_test_02.txt
modified: test_01.txt
プッシュしたくないファイルをステージングから除く
プッシュしたくないファイルをステージングから除きます。
git reset HEAD ファイル名
を実行します。
$ git reset HEAD push_test_01.txt
$ git status
On branch develop
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: push_test_02.txt
modified: test_01.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
push_test_01.txt
再コミット
正しくステージングがされていることを確認したら、もう一度コミットします。
$ git commit -m "テスト3 その2"
再プッシュ
プッシュをもう一度行います。
fオプション
を使用して強制的にプッシュします。
$ git push -f origin develop
これでプッシュしたくないファイルは、リモートリポジトリから消えました。
プッシュしなかったファイルは?
今回のpush_test_01.txt
は追跡されていないファイルなので、削除したり.gitignore
に記述したりします。
.gitignore
については、こちらの記事が参考になります。
追跡されているファイルの場合、変更(ワークツリーにある状態)自体を取り消したい場合は、git checkout ファイル名
でHEAD(最新コミット)の状態に戻すこともできます。
$ git checkout test_01.txt
この場合、既にコミットされている状態に戻るため、コマンド実行後はgit status
に表示されることはありません。
また、コミットIDを指定して、特定のコミットの状態に戻すこともできます。
おまけ
コミットはしたくないけれどブランチを切り替えたい場合は、git stash -u
をよく使います。
ファイルの一時退避に使えるコマンドです。uオプション
で、新規作成のファイルも対象に含める事ができます。
気を抜くと、ブランチもスタッシュも乱立されています・・・適宜削除しなければです。
参考記事