Rajesh
Rajesh

Reputation: 632

Git lost commits unable to find in history

We have multiple developers working on a shared git repository(they push to this).

We found that some of the commits done by a developer are lost.

We can see those commit history using gitk command(using in windows).

But when we go that the file specified in the commit shown in the gitk and see the history using git log filepath we don't see that commit at all.

We don't know how this can happen, and don't know how to recover.

We think more than 10 commits from different developers are lost in this way.

One of the strange thing is, we checked out some old commits using git checkout 034534fd and done git cherry-pick 234234321 one by one commit. While doing this we got our lost commits, but nothing is shown in the commit log of '234234321' about the affected files.

Upvotes: 5

Views: 9795

Answers (4)

Johanned Nicolai
Johanned Nicolai

Reputation: 79

As long as you have not run garbage collection in your local repository and have git reflog present, creating a new branch based on the most recent SHA-1 will work. If not, there are extensions to enterprise Git servers like Gerrit that will do what will version your branch history. If a branch gets deleted or updated in a non fast forward way (push -f) it will back the previous version under a special ref so that they can be restored if needed and will not be pruned by garbage collection. Gerrit administrators can still remove selected commits if needed for legal reasons.

Upvotes: 1

Richard Hansen
Richard Hansen

Reputation: 54273

I'm a little confused by your question. Are you saying that you can see the commits in gitk but not with git log -- filepath?

If so, your commits aren't lost; git log's history simplification is hiding them from you because it thinks they're uninteresting. If you pass the --full-history argument to git log you should see them.

Explanation

By default, when you do git log -- filepath, Git will not show you changes to that file if Git believes the change is uninteresting. This is called "history simplification". This often happens with cherry-picks.

The documentation on history simplification (see git help log) is not very well written (extremely hard to understand), but here are the key parts:

Default mode

Simplifies the history to the simplest history explaining the final state of the tree. Simplest because it prunes some side branches if the end result is the same (i.e. merging branches with the same content)

[...]

Commits are included if they are not TREESAME to any parent (though this can be changed, see --sparse below). If the commit was a merge, and it was TREESAME to one parent, follow only that parent. (Even if there are several TREESAME parents, follow only one of them.) Otherwise, follow all parents.

In other words, when Git is walking the history looking for commits that change filepath and encounters a merge commit, it doesn't always walk all parents of the merge commit. It often only picks one parent and walks only that parent's ancestors. This means that you won't see a commit modifying that file if the commit is in one of the other branches.

The --full-history argument tells git log to walk all parents, thus showing every commit that modified filepath whether Git believes it is interesting or not.

Upvotes: 13

CharlesB
CharlesB

Reputation: 90496

This can have happened either by committing in a detached HEAD, or deleting the branch the commits were on.

If you see the lost commits in reflog or rev-list, then the simplest is to re-create a branch whose tip is on last commit:

git branch recovered <most-recent-SHA1>

It is important to provide the SHA1 of the very last commit you want to retrieve, or later ones won't show.

Now commits are in a branch named recovered, so you can see them in your log. You'll most likely want to merge or rebase the recovered branch then.

Upvotes: 2

Benedikt Waldvogel
Benedikt Waldvogel

Reputation: 12906

check if the lost commit appears in the output of git reflog.

Upvotes: 5

Related Questions