コフス技術ブログ

【Git】過去にコミットする/存在を無かった事にする(不可逆過去改変)例

この記事はにメンテナンスが行われています。

Gitにて過去にコミットする例と、無かった事にする(不可逆改変)の例です。そもそも使用する機会が無いと思いますが、以下の通りに行うと可能になります。

過去にコミットする commit --amend

状況 内容
使える状況 過去にコミットしたい時。
使えない状況 過去にコミットしちゃまずい時。

方法

git commit --amend --date="Sun Feb 21 00:00:00 2016 +0900"
GIT_COMMITTER_DATE='Sun Feb 21 00:00:00 2016 +0900' git commit --amend

まず一旦普通にコミットしてしまい、その後commit —amendで日付を指定してあげます。
日付は2016/02/21(日)ならSun Feb 21 00:00:00 2016 +0900。これ以外の書式だと弾かれるので注意が必要です。

この状態で一旦指定の日付でコミットが出来ますが、GitにはCOMMITTERというデータもありこの値も変えてあげる必要があります。

GIT_COMMITTER_DATEで先程指定した日付を再度指定し、commit --amendしてあげる。これで過去にコミットすることが出来ます。

  1. 普通にコミット
  2. commit —amendで過去の日付を指定してあげる
  3. GIT_COMMITTER_DATEで過去の日付を指定してCOMMITTERのコミット日付も変更する

以上です。知っていると何時の日か使えるかもしれませんね^^

無かったことにする(不可逆改変)filter-branch

基本使う状況を作らない様にするべきではありますが、既にPush済みのファイルを完全に消したい、存在自体を過去を遡って無かったことにしたい、という場合はfilter-branchが活躍します。

ただし不可逆的に改変することになるのでGit管理の根本がズレると言えばズレます。しかしながらGitに入っていたらまずいファイルをPush後に抹殺したい時には以下の例の様に消すことが出来ます。

状況 内容
使える状況 リモートへPush済みで暫く経ってしまったけど、何らかの理由でPushしたファイルの存在自体を完全に無かったことにしたい時。
使えない状況 関係者がめちゃ多い時は安易に使えないコマンド。然るべき権限者の方が対応しましょう。

方法

hogeディレクトリを例にfilter-branchで削除する例です。

git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch hoge/" --prune-empty HEAD
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --aggressive --prune=now

行う操作の流れとしては以下の様な形を取ります。

  1. filter-branchコマンドでhogeディレクトリを不可逆的に無かったことにする
  2. その後関連する不要なファイル.git/refs/original/を削除
  3. 続いてreflogして、gcにてリポジトリのメンテを実施
  4. 後はリモートへコミットしてしまえば不可逆的な過去改変が可能

Git管理するファイル数に比例して処理時間が掛かるので、大規模なリポジトリでこの操作を行うのはあまり現実的ではないです。その場合は新たにリポジトリを作ってしまう方が圧倒的に時短になるでしょう。

実際に数千ファイル管理しているリポジトリで試してみた所1時間強掛かりました。この時間ドキドキしながら待つのも精神衛生上全くよろしくないので、テストbranchでお試しをしてから実行すると良いでしょう。(そもそも直masterで行うようなコマンドではありません;;)

不可逆的に過去改変を行うので実行後は再度リモートよりcloneする必要があります。事前にメンバーにも共有しておきましょう。