I was working on a feature locally and made a couple of commits on my master branch (instead of making a separate branch and working there). Then, I pushed those commits to my remote master branch on GitHub (which is actually a fork of another repository). Some time passed before I realized the error and more commits were added to the remote master branch. Now, I want to go back and make a separate branch for that initial feature. How would I do that?
To illustrate my problem, this is what I have:
master A - B - C - D - E - F
This is what I want:
newbranch C - D / \ master A - B ---- E - F
C, D are the initial feature that I forgot to make a new branch for.
Caveat: it’s generally considered bad practice to rewrite shared branches such as
master. You’ll want to make sure everyone who uses the repo is aware that you’re doing this.
That being said, as asked, you could do this:
# NOTE - this assumes your remote is called "origin" git fetch # create a branch called "newbranch" that points to commit hash D git branch newbranch D # checkout master so you can fix it up git switch master # change master to point to B git reset --hard B # Replay E through F (or any new commits if they exist!) onto master git cherry-pick E..origin/master # replace the remote master (make sure everyone is OK with it!) git push --force-with-lease
The results of these commands will make your two branches look like:
newbranch: A-B-C-D master: A-B-E'-F'
F' notation indicates that those commits will be similar to E and F, but with different commit IDs (because anytime you rewrite a commit you are literally making a new commit, and therefore the ID will change.)
It’s possible you’ll get conflicts at the cherry-pick command. This will happen if any of the commits after
Ddepend on either of the commits you are pulling out of
master. If that happens you may want to reconsider this action altogether.
In Git there are oftentimes many different ways to do the same thing. Note you can actually swap out the
cherry-pickcommands and do it all in one shot with a single "fancy"
rebase --onto. But conceptually I think doing a reset and then cherry-picking a range of commits is easier to understand explicitly. The rebase just does both behind the scenes.
In the cherry-pick command, the reason I suggest going from commit
origin/masterinstead of the obvious
F, is simply because you mentioned: "more commits were added to the remote master branch." In case even more are added that you don’t know about until your initial
git fetchcommand at the start of this answer, this way you will keep any new unknown commits as well.
Answered By – TTT