Reputation: 15932
I've a tree like this:
(commit 1) - master
\-- (commit 2) - (commit 3) - demo
\-- (commit 4) - (commit 5) - PRO
and I have to move the PRO branch to master
(commit 1) - master
|-- (commit 2) - (commit 3) - demo
\-- (commit 4) - (commit 5) - PRO
I've tried a git rebase master
from PRO branch, but nothing happens.
To clarify: I was working in master and then I had to make a product demo (git checkout -b demo
and some commits). Then, by mistake, I create another branch from demo (git checkout -b PRO
and some commits) and now I need to move PRO branch to master and leave demo intact. At the end, both demo and PRO will hang from master.
Upvotes: 381
Views: 277130
Reputation: 12234
Another option not mentioned yet would be to use interactive rebase where you can simply mark commit 2 & commit 3
to be removed and only keep commit 1 & commit 4 & commit 5
.
# Run interactive rebase
git rebase -i HEAD^5
# rebase options will get displayed in text editor
pick a89b78c Commit1
pick b136d0a Commit2
pick c231e8d Commit3
pick d54274b Commit4
pick e87218e Commit5
# keep lines with commits you want in branch and save file
pick a89b78c Commit1
pick d54274b Commit4
pick e87218e Commit5
Upvotes: 0
Reputation: 161627
Assuming newBase
is the branch you want to move your commits onto, oldBase
is the old basis for your branch, you can use --onto
for that:
git rebase --onto newBase oldBase feature/branch
Given your case:
git checkout PRO # Just to be clear which branch to be on.
git rebase --onto master demo PRO
Basically, you take all the commits from after demo
up to and including PRO
, and rebase them onto the master
commit.
Upvotes: 715
Reputation: 59
I had a slightly different approach using reset and stashes that avoids deleting and re-creating branches as well as eliminating the need to switch branches:
$ git checkout PRO
$ git reset commit4 # This will set PROs HEAD to be at commit 4, and leave the modified commit 5 files in ur working index
$ git stash save -m "Commit message"
$ git reset commit3
$ git stash save -m "Commit message"
$ git reset master --hard
$ git stash pop
$ git stash pop
$ git push --force # force if its already been push remotely
By resetting the branch on a commit-by-commit basis your basically just rewinding that branches history a commit at a time.
Upvotes: 5
Reputation: 24194
Checkout to PRO
branch, Copy the oldest (commit4) and latest (commit5) commit hashes of this branch and paste somewhere else:
$ git checkout PRO
$ git log # see the commit history
# copy the oldest & latest commit-hash
Delete the PRO
branch (keep a backup just for safety). Create and checkout to a new PRO
branch from master
:
$ git branch PRO.bac # create a new branch PRO.bac = PRO as backup
$ git checkout master
$ git branch -D PRO # delete the local PRO branch
$ git checkout -b PRO # create and checkout to a new 'PRO' branch from 'master'
Take (cherry-pick) the range of commits of Previous PRO
branch into the new PRO
branch:
$ git cherry-pick commit4^..commit5 # cherry-pick range of commits
# note the '^' after commit4
Now, if all is ok, then do force (-f) push to remote PRO
branch and delete local PRO.bac
branch:
$ git log # check the commit history
$ git push -f origin HEAD # replace the remote PRO by local PRO branch history
# git branch -D PRO.bac # delete local PRO.bac branch
Upvotes: 46
Reputation: 4074
I will try to be as generic as I can be. First, be sure that you are on the desired branch:
git checkout current-branch
Then use the following command (where new-base-branch
is the branch which you want to be your new base, and current-base-branch
is the branch which is your current base.)
git rebase --onto new-base-branch current-base-branch
If you do not have conflicts, then great - you are done. If you do (in most cases), then please read on.
Conflicts might arise, and you will have to resolve them manually. Git now tries to do a "3-way merge" between your current-branch
, current-base-branch
and new-base-branch
. Roughly this is how git will work internally:
Git will first rebase the current-base-branch
on top of the new-base-branch
. There might be conflicts; which you will have to resolve manually. After that is done, you usually do git add .
and git rebase --continue
. It will create a new temporary commit temp-commit-hash
for this.
After this, Git will now rebase your current-branch
on top of temp-commit-hash
. There might be further conflicts and again you will have to resolve them manually. Once done, you continue again with git add .
and git rebase --continue
, after which you have successfully rebased your current-branch
on top the new-base-branch
.
Note: If you start to mess up, then you can do git rebase --abort
anytime during the rebase process and get back to the starting point.
Upvotes: 71