Assume I have two branches, master and new_feature
I was supposed to work on a specific feature, I thought this feature would be part of new_feature so, I checked out specific_feature branch out of the new_feature branch, like so
git checkout -b specific_feature
Now I did a lot development in this specific_feature branch, merged upstream/new_feature into it a couple of times to get the remote changes.
Now, I come to know that my specific_feature should have been branched out of master not new_feature. (new_feature branch is not ready to be pushed)
Is there a way I can take the diff between my specific_feature branch and new_feature branch, and apply those changes to new branch say specific_feature_master (branched out of master)?
That seems a job for git rebase --onto:
git rebase --onto master new_feature specific_feature
That will take only the commits after new_feature up to specific_feature HEAD, and replay them onto master.
Note that you will then have to force push specific_feature to upstream (if you already pushed it before): git push --force specific_feature.
That can be an issue if others have already pulled that branch and are working on it.
davidriod correctly points out that:
I don't think this will work as the OP as merged several times the
upstream/new_featurebranch in the specific_feature branch
If new_feature was never updated (fetch only, never pull), then it might still work.
If new_feature was updated (pull) and merged into specific_feature, then the rebase --onto would only play the last few commits since the last merge: here, only z' commits would be replayed, not the first z.
x--x--x
\
y--y--Y--y--y (new_feature)
\ \
z--M--z'--z' (specific_feature)
Instead of cherry-picking, I would:
specific_feature out of master (and mark the specific_feature branch as tmp)Y (the last new_feature commit which was merged in specifc_feature) into the new specific_feature branchThat is:
git checkout -b tmp specific_feature
git checkout -B specific_feature master
git merge $(git merge-base tmp new_feature) # that merges Y
----------M (specific_feature)
/ /
x--x--x /
\ /
y--y--Y--y--y (new_feature)
\ \
z--M--z'--z' (tmp)
Then the rebase --onto can use that same common ancestor Y as the correct base:
git rebase --onto specific_feature $(git merge-base tmp new_feature) tmp
git branch -D tmp
----------M--z''--z'' (specific_feature)
/ /
x--x--x /
\ /
y--y--Y--y--y (new_feature)
You may use use the command git cherry to retrieve the commit done on the specific_feature branch and which does not appear on the origin/new_feature branch.
git cherry origin/new_feature specific_feature
You can then create a new branch from master and cherry-pick all these commits. But if you dependencies between your development on specific_feature and origin/new_feature no scm is going to resolve that for you.
git checkout -b specific_feature_master master
git cherry origin/new_feature specific_feature | egrep '^+' | awk '{print $2} | xargs git cherry-pick
Something like that should do starting point for resolving your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With