git merge branch in a zipper like fashion
i have an Git repo with for example two branches “master” and “other”. They contain commits almost to one subfolder each, so there is no collision at revision time in history. Now I like to delete the branch “other”; and merge it’s commits into “master” in a zipper-like fashion, eg:
Master A1 A2 - - - M3 M4 Other B1 - - - B2 - - B3
Master A1 B1 A2 B2 M3 M4 B3
and “other” vanishes. So only one linear master branch is left.
Is this possible with Git’s toolkit?
4 Solutions collect form web for “git merge branch in a zipper like fashion”
First off, are you sure this is what you want to do? There are two fairly standard solutions for this sort of situation in Git, but neither of them “zips” the commits up in exactly the way you want. The first option is just to merge “other” into “master”, and delete the “other” branch. This does not leave you with a linear history, but everything is in the “master” branch, and you can look at the revisions in any particular order that you want (for instance, you can do
git log --date-order to get the commits listed in the order that you want). You will get this history in the end:
A1 A2 M3 M4 *--*--*--* / \ --* *-- < master \ / *----*---* B1 B2 B3
You would achieve this by running:
git checkout master git merge other git branch -d other
The other option is to rebase your “other” branch on top of your master branch. This will give you a linear history, but all of your commits on the “other” branch will appear after the commits on “master.” The dates will be preserved, so if you want to know when the commits actually happened, you can still find that out, but topologically, they’ll be sorted afterwards:
A1 A2 M3 M4 B1 B2 B3 --*--*--*--*--*--*--*-- < master
You can do this by running:
git checkout other git rebase master git checkout master git merge other git branch -d other
If you’re absolutely certain that neither of the above work for you, you can consider the “zipper” approach that you’re trying to do. There are no automated tools that come with Git that will do this for you, so you’re going to have to work a little harder for this. It will also cause problems for anyone who is basing their history on
master, as they will all then have to rebase their work on top of your new
master (your proposed linear history changes the parents of each of the commits in master, which means that those commits are different than they were before, which means that anyone else is now basing their work on an entirely new set of commits, that just happen to have the same diffs as the previous set of commits).
If you don’t mind doing the ordering manually, you could use
git rebase -i to order the commits however you want. You would run the following commands (where
base is the first commit before the two branches diverged; if
a1 is the first commit not in common between them, then you could use
a1~ to refer to this commit):
git checkout master git merge other git rebase -i base
During the interactive rebase, you will presented with a text file containing a list of changes, which you can edit into whichever order you want them to be applied in. This is entirely manual, of course, so only an option if you have a short history and want to rearrange the commits manually. If there are any merge conflicts, you may have to resolve them manually multiple times if you do this. And as mentioned, this will mean that anyone else who was basing their work on
master will now have to rebase as well.
You could also automate this process somewhat, by creating a new branch starting at
base, and cherrypicking commits from one branch or the other to this new one, and finally replacing
master with this new branch.
But as I mentioned, you probably don’t want to do this. My first two solutions, which don’t give you quite the history that you’re looking for, but do give you something close to it, will behave the best in most Git-based workflows.
Maybe you could merge Other into Master, then run a
git rebase -i A1 to interactively rebase – rearrange the commits in the text editor to your liking. You’d still have a merge commit to deal with, probably.
And I wouldn’t rebase if you’ve already pushed to another repository otherwise you’d be changing history and the commits wouldn’t line up.
Create another branch named
git cherry-pick relevant commits in order into
temp. Rename branch
git branch -M master.
If you don’t care about the actual order of commits and this would be OK:
A1 A2 M3 M4 B1 B2 B3
Then on branch Other do
git rebase master.