Search code examples
gitbitbucketgit-mergeatlassian-sourcetreegit-revert

Did we bork our repository? -- merged wrong way, then reverted, now merging the other way does something weird


  • We have Dev, our long term release branch (not Master, don't ask why)
  • We also have FeatureBranch, an old branch with many commits/pushes
  • I mistakenly merged Dev to FeatureBranch rather than the other way, so Dev commits were applied to FeatureBranch (d5de75c)
  • I did this using SourceTree; conflicts arose; I resolved them
  • We reverted FeatureBranch to the commit before the bad merge
  • We then merged FeatureBranch to Dev, this time via pull request from Bitbucket (78e4c0f)
  • No conflicts arose this time!
  • This operation appeared to undo commits that were on Dev
  • Is this because revert commits are now on FeatureBranch?
  • We have reverted the merge (ae2bf73)

What's the best way to merge FeatureBranch to Dev now? I'm tempted to force push to FeatureBranch from before the debauchery began, then try merging again, hoping for different behavior. We are a small team with very few local changes, so we can adapt fairly easy to an altered origin history, but still, I'd like to avoid a force push if possible.

git log; I'm locally reset to f0e83d1:

 *   ae2bf73 (origin/Dev, Dev) Merged in undo22 (pull request #23)
 |\  
 | * d0292f4 (origin/undo22) Revert "Merge FeatureBranch to Dev (pull request #22)"
 |/  
 *   78e4c0f Merged in FeatureBranch (pull request #22)
 |\  
 | * 3c2f132 (origin/FeatureBranch) Re-adding accidentally reverted change.
 | * f586c2e Revert "Merge branch 'Dev' into FeatureBranch"
 | * e996bcc Revert "#IC-67 #IC-179 [Redacted]"
 | *   d5de75c Merge branch 'Dev' into FeatureBranch
 | |\  
 | * | f0e83d1 (HEAD -> FeatureBranch) #IC-67 #IC-179 [Redacted]

Solution

  • revert creates a new commit, which essentially erases changes that came before it.

    When you created a revert commit on FeatureBranch, it became a new commit that essentially erased the changes on Dev. You then merged that commit into Dev.

    However... not all is lost.

    In this kind of extreme scenario, sometimes the best course of action is to do something that's a bit insane: Rewrite History. Please note that this should be undertaken with some caution, so read up before committing to this course of action. (No pun intended.)

    1. Checkout your Dev branch.

    2. Look at your commit history.

    3. Write down the current HEAD hash id for your Dev branch. You may need it in case things go sideways.

    4. Now find the last commit before the shenanigans began, then locally run git reset --hard COMMIT_HASH_ID (replacing "COMMIT_HASH_ID" with the commit id, e.g. 3daee367b). This is like a revert, except that instead of creating a new commit which erases prior changes, it rolls back as if the changes had never happened.

    5. Now run git push --force-with-lease. You might need to reconfigure BitBucket to let you do this, although it sounds like you haven't protected Dev (which is likely why you are in this trouble in the first place).

      Note that this will cause a significant disruption for anyone else who has checked out Dev with these recent commits. They may also need to run git reset --hard COMMIT_HASH_ID for their local Dev branches to get back on track. (They will not need to push, though.)

    (You can repeat these steps for FeatureBranch if you need to.)

    Now got to BitBucket and protect your Dev branch to prevent these kinds of accidents in the future.