I just had a really weird problem with git. I pushed a commit yesterday and after that a few people did pushes. Now I can see my commit in history on github, but the changes I made are not in the HEAD revision of the file and if I look at the history of the individual file, my commit doesn't show up. My team mates tell me that all they did were regular pull and push. There were no conflicts with the file I changed. If someone used force push, I would expect my commit to completely disappear. If someone screwed up a merge conflict resoltuion, I would expect merge commit to undo my changes and be reflected in the commit history for the file. But somehow neither is the case. To simplify:
How does something like this happen?
Edit: per discussion in the comments, here is a piece of my commit graph
* | 8c1d372 ... * | 98dbad7 Merge branch 'master' |\ \ | * | 8d64a09 ... | * | 12beb68 ... | * | 1c94b6d Merge branch 'master' | |\ \ | | * | 80b6285 ... | | * | 9781fad ... | | * | f12fc90 ... | | * | 61411fa ... | | * | 291333b ... | * | | aeee93f ... | |/ / | * | bcfbf65 Merge branch 'master'
My commit that disappeared is 9781fad. If I checkout 8c1d372 my changes disappear. Yet no commits after mine actually affect the file I changed.
There are many ways to rewrite history with git. Use git commit --amend to change your latest log message. Use git commit --amend to make modifications to the most recent commit. Use git rebase to combine commits and modify history of a branch.
To find out which files changed in a given commit, use the git log --raw command. It's the fastest and simplest way to get insight into which files a commit affects.
Use --follow option in git log to view a file's history This lists out the commits of both the files.
Actual answer (rather than super-long comment).
Here's the graph bits again, plus my own annotations:
* | 8c1d372 ... <-- lacks desired changes
* | 98dbad7 Merge branch 'master' <-- ? (interesting #1)
|\ \
| * | 8d64a09 ...
| * | 12beb68 ...
| * | 1c94b6d Merge branch 'master' <-- ? (interesting #2)
| |\ \
| | * | 80b6285 ... <-- probably also has desired changes
| | * | 9781fad ... <-- is commit that makes desired changes
| | * | f12fc90 ...
| | * | 61411fa ...
| | * | 291333b ...
| * | | aeee93f ...
| |/ /
| * | bcfbf65 Merge branch 'master'
Since no one explicitly reverted your changes, and they're to a file no one else should have been editing, it's almost certain that whoever lost your changes, did so by doing a bad merge.
There are two merges that are interesting, which I have marked. #1, commit 98dbad7
, has two parents: one we cannot see (off the bottom of the graph) and one we can, 8d64a09
. A git log
from this point will show both histories. git show 98dbad7:path/to/file
will show the version of the file attached to the merge commit (i.e., whatever whoever did the merge said was the correct version of that file). If that's the wrong version—if that file lacks the desired changes—then either the merge itself went bad, or had bad inputs. Presumably the parent-that's-off-the-bottom is not supposed to have the change, so at this point we should follow the other parent, i.e., 8d64a09
.
You can git show 8d64a09:path/to/file
to see if that version has, or is missing, your changes. If your changes are in there then it is the 98dbad7
commit that dropped them. If your changes are not in there, we should press on.
For completeness we can look at 12beb68
, but it's probably not the culprit. It's an ordinary commit with one parent, 1c94b6d
.
Commit 1c94b6d
is our second interesting merge. As with any merge, it has two (or more, but usually two) parents. This time we can see both, and they are commits 80b6285
and aeee93f
.
Commit 80b6285
probably has your changes, since it's an ordinary commit whose parent, 9781fad
, is the commit with your changes. And commit aeee93f
won't have your changes since it's from the side of the merge that, well, doesn't have your changes. :-) You can git show 80b6285:path/to/file
just to check that whoever made that commit didn't secretly (as opposed to overtly) revert them, and then git show 1c94b6d:path/to/file
to observe whether it's this interesting-merge-#2 that dropped your changes.
Chances are very high that one of those merges dropped your changes. Why is still an interesting question, but has to be answered by the person who made that merge. They did something—perhaps a checkout, perhaps a flag given to the merge—that dropped your changes during the merge. Find out which merge dropped the changes, and talk to whoever did it to find out what they did that dropped them.
It's really easy to bring your changes back in: just use git cherry-pick
, which runs a diff for you, then applies that diff to the current commit. So you'd get back onto master
and simply git cherry-pick 9781fad
. That will diff 9781fad^
(9781fad
's parent, which is f12fc90
) against 9781fad
—a diff showing your changes—and apply them to the current commit and make a new commit, re-using the original message. (If your commit affects multiple files and should only bring back the changes to one file, it requires a bit more work, but assuming it's the one file, this is the easy fix. You will still need to make sure no one undoes it in a future merge, though.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With