1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gitに機密情報をコミットしてしまったときの対処法

Last updated at Posted at 2024-02-23

サーバーの秘密鍵やAPI呼び出しのトークンといった機密情報を間違ってGit commitに入れてしまったとき、どうしたらよいのかまとめました。原則として、機密情報はcommitに入れてはいけません。.gitignoreを活用して、commitに絶対に含まれない仕組みづくりが大切です。

でも、新規開発の時など開発環境があわただしいときは、ふとした瞬間に機密情報がcommitに紛れ込んでしまう場合もなくはないですよね。。。

結論

  • ローカルレポジトリへのcommitだけなら、commitへの参照をすべて消去してgit gcすることでcommitを消去できます。 => 対処法3
  • GitHubにpushしてしまった後なら、GitHubのサポートに連絡して消してもらうしかないです。ただ、それ以外にも善後策はあります。 => GitHubにpush済みの場合

対処法1: revert (おすすめしませんが簡単です)

git revertコマンドをつかってcommitを打ち消します。こうすることで、「見かけ上は」機密情報を入れてしまったcommitをなかったことにできます。

git revert <commit>

「見かけ上」といったのは、commit履歴に機密情報commitが残ってしまうため、後からいくらでも機密情報を参照できてしまうからです。

例えば、コード追加 -> 機密情報追加 -> テスト追加の順番でcommitをした後、機密情報追加のcommitをrevertで打ち消すことを考えます。

$ git commit -m "add code"
$ git commit -m "add secret"
$ git commit -m "add test"

$ git revert HEAD~

すると、機密情報はブランチから削除することができますが、commit履歴にはしっかりと残ってしまいます。

$ git log --oneline

427d14d Revert "add cred"
0b17cbe add test
8476fcd add cred
87996b0 add code

そのため、機密情報commitを指定してcheckoutすれば機密情報を見ることができてしまいます。

$ git checkout 8476fcd
$ cat <credential> # => 機密情報が表示される!!!

なんだかCTFの問題にでてきそうな状況ですね。。。

対処法2: rebase (まあ悪くないです)

rebaseを使ってcommit履歴を書き換えて機密情報commitを削除しましょう。

$ git commit -m "add code"
$ git commit -m "add secret"
$ git commit -m "add test"

$ git rebase -i HEAD~2

git rebase-iオプションをつけると、rebaseがインタラクティブモードで起動します。

pick 8476fcd add cred
pick 0b17cbe add test

今回は8476fcdのcommitを削除したいので、この部分のpickをdropに変えます。

drop 8476fcd add cred
pick 0b17cbe add test

すると、commit履歴から機密情報commitが削除されます。

$ git log --oneline

41b8d7c add test
87996b0 add code

万事OKかと思いきや、実はcommit hashを使うと機密情報commitにcheckoutができてしまいます。

$ git checkout 8476fcd
$ cat <credential> # => 機密情報が表示される

なぜかというと、gitはcommit履歴からcommitが削除されても、すぐにはcommitの情報を消去しないからです。これには理由があって、例えばgit reset HEAD~で間違ってresetしてしまったときなどに、元のcommitに戻るときなどに使われています。

$ git reset HEAD~ # 間違えた!!
$ git reflog

41b8d7c (HEAD -> main) HEAD@{0}: reset: moving to HEAD~
58f92da (HEAD -> main) HEAD@{1}: ...

$ git reset HEAD@{1} # => もとのcommitに戻る

rebase後のcommmit状況は以下のようになっています。

rebaseによってmainブランチではコード追加commitの直後にテスト追加commitが移動しています。ただ、機密情報追加commitも情報としては残っていて、ブランチからは参照されない宙ぶらりん(dangling)の状態になっています。

この状態のcommitは、いずれは(通常90日で)gitのgarbage collectionによって消去されるので、このまま放置していてもダメというわけではないです。(参考: Atlassian Git Tutorial)

対処法3: rebase + gc (面倒だけど確実)

rebaseにgcを組み合わせて、commitを完全に消去しましょう。

$ git rebase -i <commit>
$ git reflog expire --expire=now --all # reflogを消去
$ git gc --aggressive --prune=now # commitを消去

gitのgc(garbase collection)は、どこからも参照されていないcommitを消去するための仕組みです。今回は、rebaseでブランチのcommit履歴から削除した機密情報commitを消去するために使います。

git gcを実行する前に、reflogを消去する必要があります。というのも、commitへの参照はブランチからの参照のほかにreflogからの参照も含まれるからです。

GitHubにpush済みの場合

これまで見てきた対処法はローカルブランチで機密情報をcommitしてしまった場合についてのものです。もし、ローカルブランチでcommitした後、GitHubにpushしていると、commitの消去は難しくなります。

手順としては以下の通りです。

  1. 対処法2または対処法3を使ってローカルブランチから機密情報を削除します。
  2. GitHub サポート ポータルに連絡して、GitHubレポジトリから機密情報を削除します。

これで機密情報のcommitを削除できます。とはいえ、一度GitHubにpushした機密情報は、漏洩したものとみなすほうがよいです。機密情報の性質に応じて、漏洩時の処理を行ってください。

GitHubにpushした機密情報がサーバー秘密鍵などだった場合は、鍵の無効化によって漏洩に対処できます。その場合、commitを急いで消去する必要性は低くなるため、GitHub サポート ポータルへの連絡はしなくてもよいかもしれません。

参考: リポジトリからの機微なデータの削除

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?