Switching Git workflow from merge to rebase: how to clean up a merge commit history?

197 views Asked by At

I'm trying to have a good Git workflow for contributing to an open source project (Endless Sky), but learning as I started out I've not ended up with a clean history. My workflow now is:

  1. upstream/master is here.
  2. My fork is here. I started using GitHub Desktop, but am beginning to switch to the command line.
  3. My fork's master is supposed to mirror the upstream/master. Each feature I develop has a branch to itself, created from my master, and I use my own (local) alpha and (pushed) beta branches for combining my features to test/play.

My problem is on my forked master: This branch is 15 commits ahead of endless-sky:master. No files changed; it's merge commit messages. This seemed ugly to me, so I did some reading, particularly the article Stop using 'git pull': A better workflow, and I've switched to rebasing/fast-forwarding.

But what's the best way to clean up an existing merge commit history in this situation? It touches a few of my feature branches too (see: feature/JammingHaywire), and I don't want to be submitting a PR where the meaningful commits are drowned by meaningless merge commits.

I've read various other questions and am not quite clear whether I'm best:

  1. deleting/remaking master — is that safe, particularly with GitHub?
  2. trying to do a git rebase -i [which commit?] back to some point — doesn't seem to work. Tried it back to 0facf00, some commit long before I forked, and my merge commit hashes (e.g. 3be4d97 seen on GitHub) don't show up in the text file to drop. The end result is unchanged.
  3. doing something else I haven't thought of yet? Is what I'm trying to do 'good practice' in the first place?
2

There are 2 answers

0
Scott Weldon On BEST ANSWER

Your first option, deleting and recreating master, is probably the easiest. Here's how you can clean things up:

  1. If you haven't already, switch to master:

    git checkout master
    
  2. Create a backup branch, just in case:

    git branch backup
    
  3. Reset master to match that of upstream. This is effectively the same as deleting and recreating the branch, your option 1, but only requires one command:

    git reset --hard upstream/master
    
  4. Force-push:

    git push --force-with-lease origin master
    

    Obligatory warning: Since a rebase rewrites history, this can be dangerous / disruptive for anyone else working on this branch. Be sure you clearly communicate what you have done with anyone you are collaborating with. Since this is a personal fork, I assume this won't be an issue for you.

Your master branch is now up to date with upstream/master, so on GitHub you should see:

This branch is even with endless-sky:master.

If you find later that you are missing anything, you can look through the history of backup to find it.

To fix any feature branches that were similarly mangled, do:

git checkout myfeature
git rebase -i master

Your editor will open and you will see a list of commits. Delete any lines containing the extra merges, then save and exit. Again push with --force-with-lease.

0
VonC On

My problem is on my forked master: "This branch is 15 commits ahead of endless-sky:master." No files changed; it's merge commit messages.

Let's start there:

reset your fork master to endless-sky/master

Assuming you have cloned your fork:

cd /path/to/fork/clone
git checkout master
git remote add-url endless-sky /url/of/endless-sky
git fetch endless-sky
git reset --hard endless-sky/master
git push --force

Now, checkout any of your feature branch (that you intent to make a PR from), and rebase it on your master branch (which also represents endless-sky/master now)

git checkout my_feature_branch
git rebase master
git push --force