Bus errorとSegmentation faultに困ったら見るブログ

物理の研究者による日々の研究生活のメモ書きです ( python/emacs/html/Japascript/シェルスクリプト/TeX/Mac/C言語/Linux/git/tmux/R/ポケモンGO)

【git】過去の大容量ファイルをアップロードしたコミットを跡形もなく削除したい

(過去記事のコピペなので内容が古いかも知れません)

残念ながら、この問題はまだ解決していません

色々とどん詰まりで、解決できそうにないのでひとまずメモとしてまとめておく



例えば意図せず大容量のファイル(hoge.txt)をコミットしてしまったとする
すぐにそれは間違いだと気づいて

$ git rm hoge.txt

とするも時既に遅し
.git以下にきちんと履歴として残っている


gitでは基本的に過去のコミットを消すことはできない
なぜなら、そういうことをすると他の開発者の手元で整合性が取れないことになるから

そこで1つ考えられるのが

$ git revert

というコマンド
これで消したいコミットを打ち消すようなコミットをしてくれる


しかし今回自分がやりたいのはそうではなくて、大容量のファイルを過去のコミットから完全に削除したい
過去のあるコミットの、さらに1部分だけを取り出して修正するのはいろいろと大変
最悪リポジトリの整合性を破壊してしまいかねない危険なことなのには重々注意しておくこと
なので
バックアップを取るなり、branchを切るなり、別のディレクトリでgit cloneして作業するなりするべし



参考になりそうなページ

qiita.com

support.atlassian.com

techracho.bpsinc.jp

git-scm.com



まず上の記事から シェルスクリプト git_find_big.sh というのを落としてくる(たぶんリンク切れてる)

$ chmod +x git_find_big.sh
$ ./git_find_big.sh

で一番ファイルサイズが大きいものを探す
左端の列がファイルサイズ(おそらく単位はキロバイト)

これをコミットログの中から探し出して、完全に亡き者にする

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch hoge.txt" --prune-empty -- --all

上記スクリプトを参考にしてhoge.txtの部分を消したいファイルを置き換える

$ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
$ /bin/rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now

で、削除したかった hoge.txt がリポジトリからなくなるはず
最初に表示されたファイルサイズ程度(もしくはそれ以上)の容量が減っているはず


と、ここまではいいのだが
上記のコマンドを走らせる前後でコミットログを見比べると、コミットのハッシュが書き変わっている・・・

$ git log

で一番上に出てくる英数字の並びのこと

そんなことはおかまいなしに

$ git push --all --force

としてみましたが、

remote: error: denying non-fast-forward refs/heads/master (you should pull first)
To https://xxxxxx
! [remote rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://xxxxxx'

のようなエラーが出てうまくいかない・・・・

と、ここで詰まってしまっている・・・
このあと色々と試してみたがどうにもうまくいかず・・・




今の自分の現状について、わかりやすい解説を見つけた
ekrea.hatenadiary.org

↓ 引用

ここでいくつか注意点を述べる。

上記コマンドは、現在のブランチの履歴のみを書き換える。
リポジトリ内に複数のブランチが存在していた場合、他のブランチとの整合性は失われる。(もちろんoriginとの整合性も失われる。)もはや古いブランチと履歴ツリーを共有することはできない。
正確に言うと、他のブランチが持つ書き換え前のコミットと、現在のブランチが持つ書き換え後のコミットは完全に別々のコミットとして扱われる。コミットのハッシュ値が以前と変わっていることに注目してほしい。

  • allオプションをつければ、リポジトリ内の全てのブランチに対して変更を適用することができる。
  • allオプションによって、同リポジトリ内のブランチの整合性は保たれる。しかしこの方法でも、外部のリポジトリ(要するにorigin)との整合性を失うことは避けられない。

要するにこの操作は、リポジトリ自体を新しく作り直して、古いリポジトリは破棄する方法であると考えるべきである。


もはや新しいリポジトリを作った方が早い気がしてきた・・・

おそらく1つ前のコミット程度であればすぐに修正できるが
1ヶ月以上前のコミットなので、そのコミットを完全に削除しても、それはもう現状復帰ではなく「リポジトリ自体を新しく作り直して、古いリポジトリは破棄する」ということなんだろう・・・

ランキング参加中です

↓クリックしていただけると嬉しいです〜