Rebase entire development branch onto new master branch

喜你入骨 提交于 2019-12-03 14:15:22
Parker Hoyes

After some fiddling, this is what I came up with. This is a simpler, manual approach to VonC's answer.

Rebasing an Entire Development Branch

Let's assume you have a branch develop which contains the initial commit of your repository, and you'd like to rewrite history such that a master branch contains the new initial commit instead.

First off, if the inital commit on your develop branch is suitable as the initial commit on the new master branch, then you can simply create the master branch there and you're done:

$ git branch master <sha1-of-initial-commit-on-develop>

If you don't have that luxury, then you'll need to create a new empty commit that will serve as the initial commit of master.

# Create the new master branch
$ git checkout --orphan master
# Clear the working directory (we want the initial commit to be empty)
$ git rm -rf .
# Create the initial commit on master
$ git commit --allow-empty -m "Initial commit"
# Rebase the entire develop branch onto the new master branch
$ git rebase --onto master --root develop

If there were any branches coming off of the develop branch, they would've been "majorly messed up". This is because those branches (we'll call them topic branches) are still pointing to the old develop branch before it was rebased. If you had no branches coming off of the develop branch, then you're done.

Each topic branch is going to have to be rebased onto the new develop branch. To do this, we're going to follow the steps outlined in another question (Git: How to rebase to a specific commit?). For each topic branch, follow these steps.

Replace <common-ancestor> with the sha1 of the commit on the newly created develop branch where the topic branch should branch off of.

$ git branch temp <common-ancestor>
$ git checkout <topic-branch>
$ git rebase temp
$ git branch -d temp

And that's it! Keep in mind that you should not rebase on a branch that you're collaborating on with someone else.

VonC

Ideally, you would need to rewrite the full history of dev by adding a commit at the start:

# remember the first dev commit (before rebase)
git branch tmp  $(git rev-list --max-parents=0 HEAD)

# first you need a new empty branch
git checkout --orphan master
git rm -rf .

# then you apply the same steps
git commit --allow-empty -m 'root commit master'
git rebase --preserve-merges --onto master --root dev

However, as illustrated in "Rebasing a branch including all its children", that would leave all the feature branches pointing at their old dev origin (before rebase).

git branch --contains tmp | \
xargs -n 1 \
git rebase --committer-date-is-author-date --preserve-merges --onto master tmp^

That is: any branch that was accessible from the old dev first commit (tmp) needs to be rebased on master: any common commits already rebased on master won't be repeated. That will recreate the commits from the feature branches, from the new (rebased) dev branch.


Original answer:

You could simply have created the master branch from the first commit of the dev branch.

git branch $(git rev-list --max-parents=0 HEAD) master

(See "How to reference the initial commit?")

That means the first commit done on dev is also considered part of the master, which isn't entirely accurate, but easier than to rewrite the entire history of dev.

From the Git filter-branch documentation.

To set a commit (which typically is at the tip of another history) to be the parent of the current initial commit, in order to paste the other history behind the current history:

git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD

(if the parent string is empty - which happens when we are dealing with the initial commit - add graftcommit as a parent). Note that this assumes history with a single root (that is, no merge without common ancestors happened).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!