I want to create a PR with a single commit, so I checkout a new branch with commmit SHA,
git checkout -b new-branch 8517c80183607461ea
How do I create a PR from here?
I want to create a PR with a single commit, so I checkout a new branch with commmit SHA,
git checkout -b new-branch 8517c80183607461ea
How do I create a PR from here?
Because of the way Git branches work, it's not enough to make a branch off a single commit. You might drag in more commits.
For example, let's say your repository looks like this.
A - B - C [master]
\
D - E - F [feature]
master
and feature
are just labels pointing to a commit. master
points at commit C. feature
points at commit F.
Git commits do not live in isolation. They take their whole history with them. F cannot exist without E, D, C, B, and A. If you push feature
then F will bring E and D along with it (assuming C is already pushed).
Let's say you want to send a PR of only E. So you make a branch at E.
$ git checkout -b new-branch E
A - B - C [master]
\
D - E [new-branch]
\
F [feature]
All that's done is created a label called new-branch
pointing to commit E. The structure of the commits remains the same. If you then push new-branch
it will drag D along with it. This is why sometimes when you think you're pushing only a few commits the PR contains many more commits.
In order to really push just one commit, you need to detach it from its history. You can do this with a git cherry-pick
. This basically takes the commit, turns it into a patch, and patches it somewhere else.
Going back to your original repository...
A - B - C [master]
\
D - E - F [feature]
You'd make a new branch off master
.
$ git checkout -b new-branch master
[new-branch]
A - B - C [master]
\
D - E - F [feature]
(Note that nothing changed except a new branch label was made pointing at C.)
Then cherry pick E. This will copy E as a new commit on top of C. There may be conflicts, resolve them as normal.
$ git cherry-pick E
E1 [new-branch]
/
A - B - C [master]
\
D - E - F [feature]
Now you can push new-branch
and only E1 will be in the PR.
You need to push new-branch
to Github, and then open a pull request. This will include all commits reachable from 8517c80183607461ea
but not already in the history of master
.
If you want to include only 8517c80183607461ea
, then you need to rebase new-branch
onto master using git rebase -i master
, and delete all the lines except the one mentioning 8517c80183607461ea
. After the rebase, your branch new-branch
will contain the rebased 8517c80183607461ea
with its new commit ID, directly on top of master, and you can push your branch/issue a pull request.
I've had a little bit of trouble using Schwern's answer since I was making the error of being on master of a forked project while making commits (here I'm calling it a rookie mistake).
Following Schwern's graphs let's say I've forked a project at C
and proceeded on master with the other commits. Here I am adding an asterisk to signal that new changes are happening on the fork:
A - B - C - D* - E* - F* [master]
If you want to cherry-pick only some of the commits (say D
and E
) what you shouldn't do is:
git checkout -b new-branch upstream/master
git cherry-pick <hash of commit D>
git cherry-pick <hash of commit E>
git push -u origin new-branch
In this case you're trying to branch out the master at F*
and cherry picking the previous commits will get you the warning
"The previous cherry-pick is now empty, possibly due to conflict resolution."
since you're adding the same old commits on the new branch.
What you should do instead is:
git checkout -b new-branch <hash of commit E>
git push -u origin new-branch
A - B - C - D* - E* - F* - G* [master]
\
D* - E* [new-branch]
After this you're ready to make a pull request with only the selected commits.
Just edit the specific file direct on github. Github will do a patch branch automatic and so you can PR just a single file out of your branch.