3

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?

Melissa Stewart
  • 3,483
  • 11
  • 49
  • 88

4 Answers4

10

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.

Schwern
  • 153,029
  • 25
  • 195
  • 336
2

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.

user229044
  • 232,980
  • 40
  • 330
  • 338
0

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.

gibbone
  • 2,300
  • 20
  • 20
0

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.

Baba Wanga
  • 31
  • 3