Squash or remove past merge commits

I am currently working with a group of others on a project for a uni assignment. We’ve all got to use Git (much to my pleasure) and we’ve set it up so that no-one commits to the main repository on GitHub and everything is done via pull-requests.

We are also making use of the gitflow tool to coordinate development.

I act as the primary maintainer and I’ve got myself into a problem (albeit a petty one) to do with the state of the commit log.

I merge in pull requests from the others and for some reason (in some sleep deprived state) I through merge --no-ff was a fan-fucking-tastic way to check off issues from the issue tracker automatically. I have now come to my senses are realised in makes the commit log graph horrendous to read. For reference here it is below (as printed via git log --oneline --graph):

* 910f7ce Create '.travis.yml'
*   52eeef7 Merge branch 'release/0.1.1-alpha' into 'development'
|\  
| *   9c9bd36 Merge remote-tracking branch 'MiniAl/release/0.1.1-alpha' into 'release/0.1.1-alpha'
| |\  
|/ /  
| * baeb154 Introduce, or edit, the `author` tag for classes
| * ebf4b91 Set the version for classes missing the tag
| * 90b985c Add the `since` tag to members missing it
|/  
* 21f7a10 Create an Eclipse project file for Sapphire
*   7a075c3 Merge remote-tracking branch 'georgedee/development' into 'development'
|\  
| * b48077f Include JavaDoc for the Android implementation
* |   99950d1 Merge remote-tracking branch 'MiniAl/development' into 'development'
|\ \  
| |/  
|/|   
| * 1a8df92 Document the entire framework supplied by SAAF
|/  
* b40e845 Initial commit

This is clearly ugly and I would like to do one of two thing:

  • Squash the merge commits, it’s fine the commits exist I’d just like to shift it so that the merges become flat; or, alternatively

  • Remove the commits completely and and set the log so that it looks like both merges were simply merge --ff(this is the preferred action it it’s possible).

The fact that this work has been pushed to the main repo is of no concern. My group members are relatively new to Git and do not often commit. None of there work will be lost and I am happy talking them through a push -f to their forks on GitHub.

I wish simply to remove the commits that merge remote-tracking branches into local ones (‘MiniAl/development’ into ‘development’ for example, not ‘release/0.1.1-alpha’ into ‘development’). Is it possible to fix this?

Current attempts at solutions

  • I have attempted inventing some form of time-machine and prevent my past self from commit such a heinous crime (I have been informed by my physics friends that this is not yet possible).

  • I’ve tried running git rebase -i -p because others seem to have had success with this, but it comes to squashing the merge Git simply refuses and won’t tell me why. It simply states it won’t do it.

  • I’ve attempted git rebase -i but the either the work done on ‘MiniAl/development’, or ‘georgedee/development’ is lost.

  • error: could not apply ---> tried it in proper way by seeing instructions but still errors for git squash
  • Squash commits directly on feature without rebase or merge
  • git subtree push --squash does not squash
  • How to use interactive rebase on the first (root) commit of a branch?
  • How do I get git branch history to match master after a squash rebase?
  • Git squash commits with merged branch
  • How to squash all merges in a branch?
  • Can I do a real git merge without having to push the commit messages from the branch to master?
  • One Solution collect form web for “Squash or remove past merge commits”

    Removing the commits might be possible but if it is it would be very messy and would require some pretty hardcore git manipulation, possibly including hand-editing some of the index files. I think your best option is squashing the commits as you said, but I am not even sure this will work cleanly.

    The key thing is that from now on use “rebase” when pulling and Lso get enough sleep!

    Git Baby is a git and github fan, let's start git clone.