はじめに
リモートリポジトリのコミットログを削除したい時ってありませんか?
本来ならそんなことをしてはいけないのですが、それでもどうしても削除したいときは今回の方法で削除することができます。
事前準備
ここではリポジトリを作成し、コミットログを用意します。
リポジトリの作成
実施するにあたってのリポジトリを作成します。
今回は samplerepo というリポジトリ名で行います。
コミットログ作成(初回)
作成したらまずはコミットログを用意します。
% git clone git@github.com:hogehoge/samplerepo.git
Cloning into 'samplerepo'...
warning: You appear to have cloned an empty repository.
% cd samplerepo
今回は README.md を作成してそれをコミットすることでログを作成します。
% echo "# samplerepo" >> README.md
% git add README.md
% git commit -m "first commit"
[main (root-commit) 7d796d7] first commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
% git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 224 bytes | 224.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:hogehoge/samplerepo.git
* [new branch] main -> main
以下のように README.md
が追加されていることが確認できます。
コミットログ作成(2回目)
今度は test.txt を作成するコミットログを残します。
% touch test.txt
% git add test.txt
% git commit -m "test.txt"
[main 4e2d57e] test.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
% git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 277 bytes | 277.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:hogehoge/samplerepo.git
7d796d7..4e2d57e main -> main
test.txt というファイルが追加されていることが確認できます。
また、コミットログを確認すると2つのログが存在することも確認ができます。
以上で準備完了です。
コミットログの削除
それではコミットログを削除したいと思います。
今回は最初にコミットした 「first commit」 というログを削除します。
コミットログの確認
現在は以下のようなコミットログがローカルリポジトリで確認ができると思います。
% git log
commit 4e2d57e85ca9d73816973639049492b4056d22fe (HEAD -> main, origin/main)
Author: Kohei Yamada <kohei@hengjiu.jp>
Date: Mon Nov 25 22:04:34 2024 +0900
test.txt
commit 7d796d79c6f92e983fc1d68c3a65a8b31f573cfd
Author: Kohei Yamada <kohei@hengjiu.jp>
Date: Mon Nov 25 22:02:07 2024 +0900
first commit
削除ではここで確認できるハッシュ値を使います。
コミット履歴の削除
先ほど確認した 「first commit」 のハッシュ値を使って以下のようにコマンドを実行します。
7d796d79c6f92e983fc1d68c3a65a8b31f573cfd
の部分は適宜置き換えてください。
% git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "7d796d79c6f92e983fc1d68c3a65a8b31f573cfd" ]; then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
Rewrite 4e2d57e85ca9d73816973639049492b4056d22fe (2/2) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/main' was rewritten
改めてログを確認するとローカルリポジトリでは削除されていることが確認できます。
% git log
commit 04d43daf983095854a595126b484cd5d4561eb05 (HEAD -> main)
Author: Kohei Yamada <kohei@hengjiu.jp>
Date: Mon Nov 25 22:04:34 2024 +0900
test.txt
この状態でリモートリポジトリへプッシュします。
通常のプッシュだとエラーになるため --force
オプションを付けて強制的にプッシュします。
% git push --force
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 266 bytes | 266.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:hogehoge/samplerepo.git
+ 4e2d57e...04d43da main -> main (forced update)
リモートリポジトリでも履歴が削除されていることが確認できました。
以上でコミットログの削除については以上となります。
コミットログを全て削除してみる
気になったので試してみたいと思います。
もう一つのコミットログも同じ方法で削除してみます。
% git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "04d43daf983095854a595126b484cd5d4561eb05" ]; then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
無事に削除できたのかなと思いきや、
Cannot create a new backup. A previous backup already exists in refs/original/
というメッセージが表示されています。
このエラーについて調べたところ、Gitのバックアップシステムに関する問題とのことです。
Gitではフィルタリング操作(例えば git filter-branch
を使った履歴の変更)を行うと、元の参照が refs/original/
にバックアップされます。ですが、今回のような対応を行った後だとすでにバックアップが存在してしまうため、再度実施しようとすると新しいバックアップを作成できずこのエラーが発生しまうとのことです。
実際に git log
で確認したところコミット履歴は削除されていないことがわかります。
% git log
commit 04d43daf983095854a595126b484cd5d4561eb05 (HEAD -> main)
Author: Kohei Yamada <kohei@hengjiu.jp>
Date: Mon Nov 25 22:04:34 2024 +0900
test.txt
これを解消するためにはバックアップを削除する必要があります。
% rm -rf .git/refs/original/refs/heads/main
それでは改めて履歴の削除を行います。
% git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "4e2d57e85ca9d73816973639049492b4056d22fe" ]; then
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
Rewrite 4e2d57e85ca9d73816973639049492b4056d22fe (1/1) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/main' was deleted
fatal: Not a valid object name HEAD
無事に削除ができたみたいです。
% git log
fatal: your current branch 'main' does not have any commits yet
今度は
fatal: Not a valid object name HEAD
というメッセージが表示されましたが、これは Git が現在のリポジトリに有効な HEAD がない( HEAD がどのブランチやコミットも指していない)という意味になります。
今回の処理で履歴を全部削除してしまった状態なのでこのメッセージが表示されたようです。
実際にbranchを確認してみると何も表示されません。
% git branch
履歴を全て削除したことで HEAD がどれを指しているかの履歴も消えてしまったようです。
この場合は pull をすれば元に戻ります。
% git pull
% git branch
* main
ということでコミットログは削除できるが全てのコミットログを削除することはできないということがわかりました。
おわりに
普段はブランチ切ってコミットしてマージしてという単純なことしか行ってなかったので、今回のようなことをきっかけに Git への知識が少し深まったかなと思います。
参考