Skip to main content

コミットが GitHub にはありますが、ローカルにはありません

特定のコミットが、GitHub AE上では見えるにもかかわらず、リポジトリのローカルクローンの中には存在しない、という場合があります。

特定のコミットを表示するため、コマンド ラインで git show を使うと、致命的エラーが発生することがあります。

たとえば、ローカルで bad object エラーが発生する場合があります。

$ git show 1095ff3d0153115e75b7bca2c09e5136845b5592
> fatal: bad object 1095ff3d0153115e75b7bca2c09e5136845b5592

しかし、以下のように your enterpriseでコミットを表示すると、問題が発生しません。

github.com/$account/$repository/commit/1095ff3d0153115e75b7bca2c09e5136845b5592

この場合、以下の原因が考えられます:

  • ローカルのリポジトリが古い。
  • そのコミットが属するブランチが削除されたため、コミットが参照できなくなっている。
  • 誰かがコミットをフォースプッシュで上書きした。

ローカルのリポジトリが古い

ローカルのリポジトリがまだコミットを取得していないことも考えられます。 リモート リポジトリからローカル クローンに情報を取得するには、以下のように git fetch を使用します。

$ git fetch remote

これにより、チェックアウトしたファイルに変更が加えられることなく、リモート リポジトリからローカル クローンに、情報が安全にコピーされます。フォーク元のリポジトリから情報を取得するには git fetch upstream を使用します。また、クローンのみを行ったリポジトリから情報を取得するには git fetch origin を使用します。

ヒント: 詳細については、Pro Git ブックの リモートの管理とデータのフェッチに関するページを参照してください。

コミットのあるブランチが削除された

リポジトリのコラボレーターが、そのコミットを含むブランチを削除した、あるいはブランチにフォース プッシュした場合、見つからないコミットは孤立している (つまり、どの参照からもたどり着けなくなっている) ため、ローカル クローンにフェッチできません。

幸いコラボレーターの誰かが、見つからないコミットを含むリポジトリのローカル クローンを持っている場合は、それを GitHub AE にプッシュして戻してもらうことができます。 コミットがローカル ブランチによって参照されていることを確認してから GitHub AE に新しいブランチとしてプッシュする必要があります。

たとえば、コラボレーターの 1 人が、コミットを含むローカル ブランチ (B と呼ぶ) をまだ持っているとします。 これが、フォース プッシュまたは削除されたブランチをトラッキングしている可能性がありますが、まだ更新されていません。 そのコミットを保持するために、そのローカル ブランチを GitHub AE の新しいブランチ (recover-B と呼ぶ) にプッシュすることができます。 この例では、upstream という名前のリモートがあり、それを介して github.com/$account/$repository へのプッシュ アクセスがあると仮定します。

コミットを持つローカルブランチを持っている人が、以下のコマンドを実行します:

$ git branch recover-B B
# Create a new local branch referencing the commit
$ git push upstream B:recover-B
# Push local B to new upstream branch, creating new reference to commit

これで、"あなた" が次を実行できます。

$ git fetch upstream recover-B
# Fetch commit into your local repository.

フォースプッシュは避けましょう

絶対に必要でない限り、フォースプッシュは避けましょう。 特に、リポジトリにプッシュできる人が 2 人以上いる場合は避けるべきです。 誰かがリポジトリにフォース プッシュした場合、フォース プッシュによって、他のユーザーがそれに基づいて作業しているコミットを上書きする可能性があります。 フォース プッシュによってリポジトリの履歴が変更され、pull request が破損する可能性あります。

参考資料