モノノフ日記

普通の日記です

Gitで「error: xxxxxxxxx does not point to a valid object!」って怒られるときの修正方法

GitHub Enterpriseで特定のリポジトリでエラーページが表示が出てるのを修正対応したんですが、書いておかないと忘れる自信があったのでblogged.

状況について

手元にgit cloneしていたリポジトリをpullしようとすると下記のような感じで怒られてました。

% git pull
error: unable to find 60c4f95fb89859e54f5fd2de864393a60fc81a08
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
Your configuration specifies to rebase against the ref 'master'
from the remote, but no such ref was fetched.

Pull Reqeustで作成されたブランチがmasterに取り込まれた後にできるマージコミット(non Fast-Forwardで作られるやつ)のobjectが生成できておらずコミットツリーが辿れないです、ってエラーだと解釈しました。 ただGitHubのWeb UI上ではPull Requestはmerge完了されていました。 しかし、.git/object配下に該当するコミットオブジェクトがない、という無限ループ感。

git ls-remoteで見ても案の定 60c4f95fb89859e54f5fd2de864393a60fc81a08 は見当たらず。。。

GitHub側の設定でDefault Branchをmasterにした状態だとリポジトリのトップページでOctocatが「ooops!!」って叫びながら500エラーを返していましたが、他のブランチに切り替えると普通に表示されてたのでmasterコミットの位置を見失ってしまってる状況に間違いないかなと断定。

f:id:Kiske:20130704120349j:plain

Default Branchをmasterにしたままgit cloneするとエラー。

% git clone xxx.git
error: unable to find 60c4f95fb89859e54f5fd2de864393a60fc81a08
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: recursion detected in die handler

Default Branch切り替えると普通にgit cloneできました。

解決方法

ここから打開方法の解説です。

大筋としてはツリーの歴史上からmasterが見つけられないのでgit push -f origin mew-master:masterでmasterブランチを強制的に上書きしてやれば解決すると推測しました。

問題になるのはnew-masterブランチをどうやって作るか。

まず、この状況になってからはmasterに対して、どのユーザも変更を入れることができていないことを確認しました。GitHub EnterpriseのAdmin toolで閲覧できる操作ログでも確認して、とある時刻から変更が入ってないことを見て一安心。

最新のPull Requestのhead commitを見るとなんと発生時刻直前の状態のブランチ。いきなり当たった。ただ1つ前に出されたPull Reqeust(#1983)の変更は入ってなかったので、これは手で修正しました。(テンプレートファイル2つの修正だけで助かった...) あと、git resetでPull Requestで取り込んで欲しいコミットはログから消してます。

git fetch origin refs/pull/1984/head
git co FETCH_HEAD
git co -b new-master
git reset --hard HEAD~
vi hogehoge # 1つ前のpull reqで取り込まれてた修正を追加

これでnew-masterブランチができました。 最初は単純にgit push -fでmasterブランチを強制的に上書きしようとしたんですがエラー。

% git push -f origin new-master:master
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
Counting objects: 19, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 767 bytes, done.
Total 10 (delta 6), reused 3 (delta 0)
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
error: Ref refs/heads/master is at 60c4f95fb89859e54f5fd2de864393a60fc81a08 but expected 0000000000000000000000000000000000000000
remote: error: failed to lock refs/heads/master
To git@foobar.jp:hogehoge/xxxx.git
 ! [remote rejected] new-master -> master (failed to lock)
error: failed to push some refs to 'git@foobar.jp:hogehoge/xxxx.git'

うーむ。refs/pull/1983/mergeからmasterを辿ろうとしてるところを解消して上げないとダメみたいです。

もう該当のPull Request(#1983)を歴史から無かったことにできないかなーと思ってググってたらQuora先生にそれっぽい記述がありました。 http://www.quora.com/GitHub/What-are-ways-to-delete-a-pull-request-on-GitHub

Pull Requestするときに生成されるrefs配下のペアのコミットを消すといけるかも、ということで消してやりました。new-masterには削除するPull Requestの修正分は反映してるし大丈夫!

% git push origin :refs/pull/1983/head
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
remote: warning: Allowing deletion of corrupt ref.
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
 - [deleted]         refs/pull/1983/head

わーい、消えました。こんなにサクッと削除できることを知り逆に恐怖。 そしてnew-masterをmasterへ。

% git push -f origin new-master:master
Counting objects: 19, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 767 bytes, done.
Total 10 (delta 6), reused 3 (delta 0)
 * [new branch]      new-master -> master

これで問題解決できました。 git周りのトラブルは影響範囲が大きいので起きて欲しくないですね><