I've performed a git filter-branch --index-filter 'git rm --cached --ignore-unmatched badfiles/ badfiles2/' --prune-empty
(per here) to remove a bunch of files in preparation for moving the remaining files to another repository. --prune-empty
gets rid of any resulting empty-commits, but it doesn't act on merges, which makes sense.
Now the history for this particular repo looks pretty ugly with a bunch of merges that don't actually add anything and some merges that are just merges of other merges that didn't actually add any changes (in the rewritten history; they may have been 'useful' before the filter-branch).
Consider this annotated snippet (generated with git log --graph --oneline --shortstat
):
* 575e3b5 Merge pull request #68 from chris/feature # KEEP THIS MERGE!
|\
| * 5dbc3f1 Actual feature changes
| | 2 files changed, 2 insertions(+), 2 deletions(-)
| * 35abc98 Cleanup/prep
|/
| 2 files changed, 22 insertions(+), 16 deletions(-)
* c3b3d86 Merge pull request #46 from org/topic_branch-mods # USELESS-C
|\
* \ 892de05 Merge pull request #47 from org/topic_branch # USELESS-B
|\ \
| |/
|/|
| * e738d4b Merge branch 'master' into topic_branch # USELESS-A
| |\
| |/
|/|
* | 4182dac CommitMsg #40 #SQUASHED-PR
| | 2 files changed, 15 insertions(+), 6 deletions(-)
* | 3b42762 CommitMsg
|/
| 2 files changed, 29 insertions(+), 14 deletions(-)
* c4e62ba CommitMsg
| 2 files changed, 39 insertions(+), 16 deletions(-)
* c2bb13f CommitMsg
4 files changed, 241 insertions(+)
I'd like to shorten this to (obviously with different id's as appropriate):
* 575e3b5 Merge pull request #68 from chris/feature # KEEP THIS MERGE!
|\
| * 5dbc3f1 Actual feature changes
| | 2 files changed, 2 insertions(+), 2 deletions(-)
| * 35abc98 Cleanup/prep
|/
| 2 files changed, 22 insertions(+), 16 deletions(-)
* 4182dac CommitMsg #40 #SQUASHED-PR
| 2 files changed, 15 insertions(+), 6 deletions(-)
* 3b42762 CommitMsg
| 2 files changed, 29 insertions(+), 14 deletions(-)
* c4e62ba CommitMsg
| 2 files changed, 39 insertions(+), 16 deletions(-)
* c2bb13f CommitMsg
4 files changed, 241 insertions(+)
So I'd like to get rid of the 'USELESS' merges, which are all 'empty' merges (no merge changes), but I'd like to preserve the history/grouping associated with the also-'empty' KEEP merge at the top, which groups those commits together into one 'changeset'.
Or looking at another example in the traditional simplified-sideways-history:
A -- B -- C -- D ==> A -- B --- D'
\----\--/ / \-E-/
\----E
I have tried solutions to remove 'empty' merges (like this), but those remove all empty merges, and I want to keep the 'useful' empty merges as displayed in the examples...
As far as I can tell, the 'useless' empty merges don't contain any commits that aren't all the way to the left/top in the history. Is there a way to filter those out cleanly? I guess I don't really even know how to describe/define those...
Note that the given example was intentionally simple. For what it's worth, later in the history this repo looks like this, all of which I'd like to prune:
* 3d37e42 Merge pull request #239 from jim/topic-dev
|\
| * 05eaf9e Merge pull request #7 from org/master
| |\
| |/
|/|
* | 1576482 Merge pull request #193 from john/master
|\ \
| * \ 187100e Merge branch 'master' of github.com:org/repo into master
| |\ \
| * \ \ 067cc55 Merge branch 'master' of github.com:org/repo into master
| |\ \ \
| * \ \ \ a69e3d2 Merge branch 'master' of github.com:org/repo into master
| |\ \ \ \
| | |/ / /
* | | | | 0ce6813 Merge pull request #212 from jim/feature
|\ \ \ \ \
| | |_|_|/
| |/| | |
| * | | | 0f5352e Merge pull request #5 from org/master
| |\ \ \ \
| |/ / / /