A commit was reverted at work. The commit was present in the repository history, but there was no trace of it in the Github file history log.
A file history log (for a.txt
as an example here) looked like that:
$ git log --oneline -- a.txt
be9d26c (test-branch) 3 - test-branch
689ae1c 1
However we knew there were more commits on that file between 689ae1c
and be9d26c
, but we didn’t find it in Github or using git log
Finding the commit
At the time, the repository history looked like that (logs taken from the repository created below):
$ git log --oneline
0f0ad15 (HEAD -> main) Merge branch 'test-branch'
be9d26c (test-branch) 3 - test-branch
076dc52 Revert "2"
d779068 2
689ae1c 1
I expected the history to also have commits d779068
and 076dc52
in the file history, between commits 689ae1c
and be9d26c
.
Using git log --full-history --oneline -- a.txt
(still using a.txt
as the file name) didn’t list the commit, but using the --full-history
option worked:
$ git log --full-history --oneline -- a.txt
0f0ad15 (HEAD -> main) Merge branch 'test-branch'
be9d26c (test-branch) 3 - test-branch
076dc52 Revert "2"
d779068 2
689ae1c 1
Reproducing the behavior
To try to understand the behavior, I tried to reproduce it by creating a fresh repository:
$ git init repo-test # Create an empty repository
$ cd repo-test
$ echo "1" > a.txt # Create a.txt with the content 1
$ git add a.txt
$ git commit -m "1" # Commit the file
$ echo "2" > a.txt # Update a.txt with the content 2
$ git add a.txt
$ git commit -m "2" # Commit the updated file
$ git revert HEAD # Revert previous commit
At this point, the file has all the commits, even without using --full-history
:
$ git log --oneline -- a.txt
c935f73 (HEAD -> titi) Revert "2"
d779068 2
689ae1c 1
However, in my case, the history also had a merge commit from another branch, let’s try it:
$ git checkout 689ae1c -b test-branch # Create a branch from the first commit
$ echo "3" >> a.txt # Append a.txt with 3
$ echo "3" > b.txt # Create a.txt with the content 3
$ git add a.txt b.txt
$ git commit -m "2" # Commit the updated files
$ git switch main # Going back to the main branch
$ git merge test-branch --no-ff # Create a merge commit from test-branch to main
The full history is available on Github.
And then let’s view the file history for a.txt
:
git log --oneline -- a.txt
be9d26c (test-branch) 3 - test-branch
689ae1c 1
Ha! Commits d779068
and c935f73
are not listed! See on Github.
They appear as expected with --full-history
:
$ git log --full-history --oneline -- a.txt
0f0ad15 (HEAD -> main) Merge branch 'test-branch'
be9d26c (test-branch) 3 - test-branch
076dc52 Revert "2"
d779068 2
689ae1c 1
The repository is available here.
Conclusion
It seems those “ghost commits” (I don’t have a better name for commits that are here but not displayed) are triggered when:
- commits on a single file cancel each other
- a merge commit is added after the revert, having an ancestor before the revert
- the merge commit has to include a branch that also modifies the file itself, otherwise all the commits will be displayed
Git is tricky… I guess it just hides commits that amount to no changes after a merge commit (?), and I still don’t understand that behavior…