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

Question

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?

Show source
| git   | github   | rebase   | git-rewrite-history   2017-01-02 22:01 2 Answers

Answers ( 2 )

  1. 2017-01-02 23:01

    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
    
  2. 2017-01-02 23:01

    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.

◀ Go back