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) looked like this:
$ 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 could not find them on 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 include 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) did not list the commits, 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 that these “ghost commits” (I do not have a better term for commits that exist but are not displayed) are triggered when:
- commits on a single file cancel each other out
- a merge commit is added after a revert, and the merge commit has an ancestor that predates the revert
- the merge commit must include a branch that also modifies the same file. Otherwise, all the commits will be displayed
Git can be tricky… I guess it just hides commits that result in no changes after a merge commit (?). I still do not fully understand this behavior…