0

I discovered that my changes from yesterday are lost in git. I've investigated and found two fault commits that were made by one of our junior developers:

Screenshot

The selected commit message says merge but doesn't contain any reference to a commit that is merged. The next commit is actually saying "fixing failed tests" but is actually merge commit which has 0 changed, added or deleted files.

After this point, this branch was merged to develop and merged to several feature branches already.

So I know commit on this branch before the merge. I know commit on the develop that was merged.

How to fix history without losing changes? I was thinking to start with commit on the develop before merge and cherry pick all next changes avoiding this two commits. That is around 30-40 commits. Are there better strategy?

2 Answers 2

1

So I'm not sure how your developer managed to add the non-merge; it is as if he passed --squash to git merge, though that is pretty hard to do by accident.

Anyway, normally I would try to revert the merge, but what you want to do is revert the "merge" relative to the second parent, and there is no second parent in this non-merge. Reverting the real merge would have no effect, since it did not change any files. So lets try doing a "hand revert" of what the merge would have been. Let's say the fake merge's hash is abc, and the real (but empty) merge's hash is xyz. If we run the following:

git diff -3 abc xyz^2 | git apply 

Then git will (hopefully) undo some of the damage. What this command does is take the steps necessary to bring the state of the fake merge to the state of develop before the fake merge and apply those steps to the working directory. If it applies cleanly, you can then add/commit the changes. The -3 option tells apply to attempt a 3 way merge if the patch does not apply cleanly; you may want to try it both with and without that option.

Of course, it may be the case that there have been so many changes/merges since then that this doesn't help. But it's worth a shot!

Sign up to request clarification or add additional context in comments.

2 Comments

It looks like she tried to merge and got many conflicts. She resolved them but after she stashed them and after she made other changes and committed that changes. Resolve and commit were done in Android Studio but stashing in SourceTree
@EugenMartynov, I'm not sure how that would result in the commit message claiming it is a merge when it really wasn't, but maybe Android Studio does something funky. Anyway, let me know if git diff -3 abc xyz^2 | git apply works out for you.
0

The selected commit message says merge but doesn't contain any reference to a commit that is merged

This is a special commit named "merge commit"

Read all about it here: https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging

Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit, and is special in that it has more than one parent.

enter image description here


The merge commit is created when you choose to work in a no-ff (no fast forward) configuration.

The --no-ff flag prevents git merge from executing a fast-forward if it detects that your current HEAD is an ancestor of the commit you're trying to merge.

A fast-forward is when, instead of constructing a merge commit, git just moves your branch pointer to point at the incoming commit. This commonly occurs when doing a git pull without any local changes.

To understand the differences between ff and no-ff take a look on this: enter image description here

5 Comments

how can I see parents of this commit?
I don't see this commit with git log --min-parents=2 -p --cc
git show commit id and then you should see the 2 parents
One of the "merges" in his repo is not a merge at all, so he would not see 2 parents.
git show <commit hash> doesn't show it was merge, just diff

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.