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:
- make
specific_feature out of master (and mark the specific_feature branch as tmp)
- merge
Y (the last new_feature commit which was merged in specifc_feature) into the new specific_feature branch
That 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)