GitHubでやらかしたコミット履歴を(ほぼ)見えなくする方法
Gitを覚えたての初心者が一番よくやらかすミスは、パスワードやAPIキーをハードコーディングしたものをリモートリポジトリにプッシュしてしまうことじゃないだろうか。
もちろん速やかにパスワードやキーの変更をすることは前提だが、問題は恥ずかしいコミット履歴がその後も残ってしまうことだ。
そんなときにどうすればいいか、この前teratailで他の人の回答を見る機会があったので実際に試してみた。
はじめに
この方法は、ざっくり言えば歴史を改変することに等しい。多人数で開発をしているときに何の断りもなく使うと、トラブルが起こる可能性が高いので注意すること。
やらかしたコミットを作る
実際にリポジトリを作り、プッシュを2回行った。内容はteratailのAPIを叩くサンプルコードだ。
github.com
$ git log --oneline bd6c846 (HEAD -> master, origin/master) アクセストークンを追加 b7ee88e initial commit
2回目でうっかりアクセストークンが見える状態のコードをコミットし、気づかずにそのままプッシュしてしまった。この履歴を消したい。
git rebaseでコミットを消す
git rebase
は、過去のコミットを編集してコミット履歴を整理するためのコマンドである。
本来の使い方ではないが、これを使ってやらかしたコミットを履歴から消すことができる。
git rebase -i b7ee88e
のように、消したいコミットのひとつ前のコミット識別番号を指定する。
pick b41300e アクセストークンを追加 # Rebase b7ee88e..b41300e onto b7ee88e (1 command) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
エディタが開いたら、pick
の部分を変えることで様々な編集ができる。今回はdrop
に変更して保存することで、そのコミットを消せる。
$ git log --oneline b7ee88e (HEAD -> master) initial commit
やらかしたコミットが消えた。
あとはプッシュするだけ。プッシュする際は、普通にgit push origin master
とするとrejectされるので、git push --force origin master
のようにする。
今回使ったリポジトリを確認してほしい。initial commitしか見えないはずだ。
【参考】厳密には消えてない
ただしGitは歴史を全て保存するので、厳密には消えたわけではない。
git reflog
コマンドを叩くと、git logでは出てこないものも含めた全ての履歴が表示される。git rebaseで編集した跡も残っている。
$ git reflog b7ee88e (HEAD -> master, origin/master) HEAD@{0}: rebase -i (finish): returning to refs/heads/master b7ee88e (HEAD -> master, origin/master) HEAD@{1}: rebase -i (start): checkout b7ee88e b41300e HEAD@{2}: rebase -i (finish): returning to refs/heads/master b41300e HEAD@{3}: rebase -i (pick): アクセストークンを追加 27ce491 HEAD@{4}: rebase -i (pick): initial commit 9d36eb3 HEAD@{5}: rebase -i (pick): initial commit 17ff75b HEAD@{6}: rebase -i (start): checkout 17ff75b6f56acea009e986d19a152298efb7dabb bd6c846 HEAD@{7}: rebase -i (finish): returning to refs/heads/master bd6c846 HEAD@{8}: rebase -i (start): checkout HEAD~1 bd6c846 HEAD@{9}: rebase -i (finish): returning to refs/heads/master bd6c846 HEAD@{10}: rebase -i (start): checkout b7ee88e bd6c846 HEAD@{11}: commit: アクセストークンを追加 b7ee88e (HEAD -> master, origin/master) HEAD@{12}: commit (initial): initial commit
コミット識別番号がわかれば、そのコミットが見える。
GitHub上でも、以下のURLを叩くと今回やらかしたコミットが見えてしまう。
https://github.com/Udomomo/changeHistory/commit/bd6c846
もっとも、コミット識別番号がわからない限り見ることができないため、赤の他人に漏れる心配はほとんどない。
GitHub社員はユーザのリポジトリのreflogを見られるようだが、それを悪用したら当然サービスとしての信頼が失墜するので、基本的には考慮しなくてよいだろう。
注意点
- initial commitでやらかしてしまった場合、通常のrebaseでは対応できない。
このサイトによれば、git rebase -i --root
としなければいけないようだ。