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_feature
branch 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