Combination of git revert and merge results in lost file

Viewed 42

I experienced strange behaviour of git merge after using revert, respectively Reverse commit action in SourceTree.

  1. I added a file called 'new_file' to a master branch.
  2. Then I reverted the commit in master and created branch feature/2
  3. I reverted the commit on branch feature/2 as well.
  4. I created 'new_file' on branch feature/2 once more.
  5. I merged feature/2 into master, merge introduced no changes, file 'new_file' is not present in master.

Does anybody have any explanation for this behaviour?

Is anybody aware of any Git or Source option that changes this behaviour?

enter image description here

1 Answers

Unfortunately this is the expected behavior of git merge in your situation.

Here is a rough outline of how git merge works :

# starting point :
  * eacff2 (feature/2) Added new_file again
  * eacff1 Revert "Added new_file"
* | eacfmm (HEAD -> master) Revert "Added new_file"
|/
* eacfXX Added new_file

when you run git merge feature/2, git first computes the "merge base" between the current branch, master, and feature/2.
In the above diagram, it is commit eacfXX Added new_file.

Then : it looks at git diff eacfXX master and git diff eacfXX feature/2, and see how these two diffs can be combined.

In the example you post, the solution is pretty straightforward : since there are no changes at all in git diff eacfXX feature/2, git decides that keeping the state in master is the way to go.

So you end up with an end result where new_file stays deleted.


The bottom line is : git merge does not inspect the intermediate states of the merged branches, it just tries to combine the state at the tip of the branches together.

Note however that if new_file had received any modifications on feature/2 (rather than being just a verbatim copy of the original file), there would have been a merge conflict which would have prompted for a closer look.

Running git rebase origin/master from feature/2 before merging would have helped, but systematically rebasing features before merging them isn't very practical, as it would add so many occasions to trigger irrelevant merge conflicts.

The generic advice is : do review your merges, be aware that, if a git revert of a past commit landed in the main branch, double check what the feature branch did with those same files.

Related