Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove merge commits while keeping merged changes?

Tags:

git

git-merge

I have our commit log from my repo. You can see the "Merge branch...into..." commits. After these commits, the branch was merged.

I need to delete the merge commits, but not discard the changes. Default rebasing doesn't show merge commits.

screenshot of the repo history

like image 778
Jelean Thomas Avatar asked May 31 '15 19:05

Jelean Thomas


1 Answers

If you want to apply the changes of the commits without including the merge commit (which as Roland Smith pointed out is generally considered bad practice) you can use git rebase with the following workflow:

  1. Checkout the branch you want the changes to be on (let's say master): git checkout master
  2. Reset master to the commit before the merge you want to undo: git reset --hard <hash of prior commit>. Make sure there are no uncommitted changes on the branch you were working on or this command will wipe them out.
  3. Checkout the branch containing the updates you want to "merge" to master without actually merging it (let's call it dev): git checkout dev.
  4. Rebase dev onto master. This will put the HEAD commit of dev to be upstream to the most recent commit that master points to: git rebase master (see the docs for more information).
  5. Fix any merge conflicts that result during the rebase (they would have happened in a normal merge too).
  6. The rebased branch should now have all of its commits following the latest commit on master. To port this over to master, check out master (git checkout master) and merge the new branch git merge dev. This will pull the changes onto master without adding a merge commit.
  7. Once you're sure the updated master branch looks okay, you'll have to update the branch on any remote repositories too. Because you're undoing prior history, when you push the branch you'll have to use the --force (or -f) flag for the remote repo to accept the changes i.e.: git push origin master --force.

That's all there is to it. After you do this, the commits on dev that were branched off of master should now be upstream to the pre-merge commit above.

NOTE: Running rebase will permanently update the commit history for the changed branches. For safety, I recommend taking 1 of 2 methods:

  1. Per @Dacav's suggestion, keep track of the commit hashes for each branch before you update anything. If things go pear shaped, then just run git reset --hard <original_commit_hash> to put the branch back on the original commit.
  2. Make backup copies of both branches before you rebase that are pointing at the original commit:

    git checkout -b master_bk git checkout -b dev_bk

like image 162
DIMMSum Avatar answered Oct 20 '22 10:10

DIMMSum