LoginSignup
12
13

More than 5 years have passed since last update.

git filter-branchでパスワードを全ブランチの歴史から消す手順

Posted at

git filter-branch

gitのリポジトリに、パスワードやAPI KEYのような秘匿性の高い情報を突っ込んでしまい後から消したいと思った際は、git filter-branchが使えます。filter-branchは、いままでの全commitを舐めて、ヤバい情報を歴史から抹消します。

[参考] git最強のオプション filter-branch
http://qiita.com/Spring_MT/items/f60c391b5dbf569a1d12

注意

  • コミットの多いリポジトリの場合、git filter-branchは時間とリソースを食う処理なので注意しましょう。EC2のデカいインスタンスを一時的に立ててそこで処理を走らせるのもいいでしょう。
  • 過去のコミットをhashを含めすべて書き換えるため、filter-branch後は既存ブランチに対してgit pushが出来なくなります。一度、ローカルのrepoを消してから、再度cloneする必要があります。事前にメンバーへの周知をしておきましょう。
  • .gitを捨ててrepoを作りなおしたほうが手っ取り早いケースもありそう

作業領域の確保

適当にdirectoryを掘って、対象のrepoをgit cloneしておきましょう

mkdir filterbranch && cd filterbranch
git clone git@github.com:someone/coolrepo.git
cd coolrepo

処理ブランチを減らす

事前に扱うブランチを減らせるなら減らしておきましょう。以下コマンドでmerge済のremote branchを消去できます

git branch -a --merged | grep -v master | grep remotes/origin| sed -e 's% *remotes/origin/%%' | xargs -I% git push origin :%

[参考] Gitでリモートのマージ済みのブランチを一括削除する
http://qiita.com/fukayatsu/items/b1a5e1c0b98acaa6261d

置換スクリプトを書く

各コミットで実行したいscriptを書きます。パスワードのハードコードを環境変数などにreplaceするような内容が想定されます。簡単な内容なら、sedのワンライナーを用意しておけば充分でしょう。

replace.rb
Dir.glob("config/*.rb").each do |file|
  fr = File.open(file,"r")
  buf = fr.read
  buf.gsub!("some_yavai_apikey", "ENV['API_KEY']")
  buf.gsub!("some_yavai_secret", "ENV['API_SECRET']")
  fw = File.open(file,"w")
  fw.write(buf)
  fr.close
  fw.close
end

すべてのremote branchをlocalにcheckoutしておく

filter-branchの対象にするため、remote branchを引っ張ってきます

$ git branch
* master
#!/bin/bash
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master `; do
   git branch --track ${branch#remotes/origin/} $branch
done
$ git branch
  update-hoge
  remove-fuga
  refactor-foo
* master
  tweak-test

[参考] [Git]リモートブランチを全て pull する
http://wada811.blogspot.com/2014/06/git-pull-all-remote-branches-locally.html

すべてのbranchでfilter-branchを実行

スクリプトをtree-filterに食わせます。
--allオプションですべてのブランチが対象になります
分かりにくいのですが、ハイフン2つのあとに、--allを付けます

git filter-branch --tree-filter "ruby /somewhere-outside-repo/replace.rb" -- --all

時間がかかりそうなら、nohup&の間に挟んでbackground動作させて一晩寝かすとよいでしょう

push

終わったら、全branchをgit push -fして上書きしましょう。

git checkout master && git push -f origin master
git checkout update-hoge && git push -f origin update-hoge
git checkout remove-fuga && git push -f origin remove-fuga
git checkout refactor-foo && git push -f origin refactor-foo
git checkout tweak-test && git push -f origin tweak-test

お疲れ様でした! もっとスマートなやり方がある気がしますね

12
13
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
12
13