Sometimes a commit will be viewable on GitHub, but will not exist in your local clone of the repository.
git show 1095ff3d0153115e75b7bca2c09e5136845b5592 # fatal: bad object 1095ff3d0153115e75b7bca2c09e5136845b5592
yet visiting the commit at
shows the commit without any problems.
There are several possible explanations:
- Local repository is out of date
- Branch containing the commit was deleted and the commit is no longer referenced
- Someone force pushed over the commit
The simplest possible explanation is that your local repository does not yet have the commit. You can safely fetch the remote data into your local repository without making any changes to your checked out files using
git fetch <remote>. Typically you write
git fetch upstream to get data from a repository that you have forked or just
git fetch origin to retrieve data that you have simply cloned.
If a collaborator on the repository has deleted the branch containing the commit or has force pushed over the branch, the missing commit may have been orphaned (i.e. it cannot be reached from any reference) and therefore will not be fetched into your local clone.
Fortunately, if any collaborator has a local clone of the repository with the missing commit, they can push it back to GitHub. They need to make sure the commit is referenced by a local branch and then push it as a new branch to GitHub.
Let's say that the person still has a local branch (call it
B) that contains the commit. This might be tracking the branch that was force pushed or deleted and they simply haven't updated yet. To preserve the commit, they can push that local branch to a new branch (call it
recover-B) on GitHub. For this example, let's assume they have a remote named
upstream via which they have push access to
github.com/$account/$repository. The user runs:
git push upstream B:recover-B # Push local B to new upstream branch, creating new reference to commit
Now you can run:
git fetch upstream recover-B # Fetch commit into your local repository.
Tip: If this ever happens, it may be safer to first run
git branch recover-B B on the local repository (i.e. create a new local branch referencing the commit). This step is not required, but it will better isolate the local branch containing the commit from the remote one where it has been orphaned.
Generally, it is recommended to avoid force pushing to a repository unless it's absolutely necessary, even more so if more than one person can push to the repository.