「gitリポジトリからファイルを完全に消去する方法」をコマンドにしてみた

gitリポジトリに間違って追加してしまったファイル等を完全に消去する方法を紹介します。

1 % git filter-branch -f --index-filter 'git update-index --remove "filename"' HEAD
2 % git push --force

ディレクトリを削除したい場合は、ディレクトリの中身のファイルを1つずつ全て削除します。

gitリポジトリからファイルを完全に消去する方法 - Hello, world! - s21g

便利なのでコマンドにしてみた。
これをパスの通ったところに置けばいい。
(追記:echoじゃなくてcatだった)

#!/bin/sh

progname=`basename $0`
usage () {
    cat <<EOM
Usage: $progname <file>
EOM
    exit 1
}


if [ $# != 1 ]; then usage; fi
command git filter-branch \
    -f --index-filter \
    "git update-index --remove '$1'" HEAD

置く場合には「git-<好きなコマンド名>」という風にすれば、gitがもしパスに「git <サブコマンド>」なコマンドが存在するなら勝手に実行してくれる。
とりあえず自分はgit-shredにしといた。


それと一応元記事に書いてある注意点を載せておく。

ポイント

  • 上記のコマンドはワーキングディレクトリのROOTで実行する必要があります。
  • "filename"はワーキングディレクトリのROOTからの相対パスで記述します。
gitリポジトリからファイルを完全に消去する方法 - Hello, world! - s21g

テスト

$ mkdir test; cd test
$ git init
Initialized empty Git repository in /home/tyru/test/.git/
$ touch foo
$ git add .; git commit -m foo
Created initial commit 385651d: foo
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 foo
$ touch bar
$ touch privacy-file
$ git add .; git commit -m oops!    # privacy-fileを間違えてコミットしてしまった
Created commit 5f8fc50: oops!
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar
create mode 100644 privacy-file


$ ... # 気付かずに何回もコミットしてしまう。privacy-fileを消したいが面倒


$ git whatchanged   # ようやくprivacy-fileに気付く
commit 34e6ea1d37ed317672f86c1db183725329219d30
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:31:27 2009 +0900

    hoge

:000000 100644 0000000... e69de29... A  hoge

commit 7d5823dbe6c4d1acff828ea1ee9e80934615b3b1
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:31:14 2009 +0900

    baz

:000000 100644 0000000... e69de29... A  baz

commit 3c58042a872a4170b22b9d3c0946f48e9a586f82
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:28:42 2009 +0900

    oops!

:000000 100644 0000000... e69de29... A  bar
:000000 100644 0000000... e69de29... A  privacy-file

commit 385651d0e103f42fd36b83efe5cdca9dd9ded8f1
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:27:42 2009 +0900

    foo

:000000 100644 0000000... e69de29... A  foo


$ git shred privacy-file    # 全てのコミットからprivacy-fileを削除
Rewrite bfdd872e0bac1a7965f7b2dd23b471d4fd35db2d (4/4)
Ref 'refs/heads/master' was rewritten


$ git whatchanged
commit 34e6ea1d37ed317672f86c1db183725329219d30
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:31:27 2009 +0900

    hoge

:000000 100644 0000000... e69de29... A  hoge

commit 7d5823dbe6c4d1acff828ea1ee9e80934615b3b1
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:31:14 2009 +0900

    baz

:000000 100644 0000000... e69de29... A  baz

commit 3c58042a872a4170b22b9d3c0946f48e9a586f82
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:28:42 2009 +0900

    oops!

:000000 100644 0000000... e69de29... A  bar

commit 385651d0e103f42fd36b83efe5cdca9dd9ded8f1
Author: tyru <tyru.exe@gmail.com>
Date:   Fri Oct 30 12:27:42 2009 +0900

    foo

:000000 100644 0000000... e69de29... A  foo