390

I've got a project hosted on GitHub which somebody has forked. On their fork, they've created a new branch "foo" and made some changes. How do I pull their "foo" into a new branch also named "foo" in my repo?

I understand they could submit a pull request to me, but I'd like to initiate this process myself.

Assume the following:

  1. Because they forked my project, both our repos share the same 'history'
  2. Although GitHub shows their project was forked from mine, my local repository doesn't have any references to this person's project. Do I need to add theirs as a remote?
  3. I don't have a branch called "foo" yet - I don't know if I need to manually create this first.
  4. I definitely want this pulled into a separate branch and not my master.
halfer
  • 19,824
  • 17
  • 99
  • 186
Colin O'Dell
  • 8,386
  • 8
  • 38
  • 75

7 Answers7

535
git remote add coworker git://path/to/coworkers/repo.git
git fetch coworker
git checkout --track coworker/foo

This will setup a local branch foo, tracking the remote branch coworker/foo. So when your co-worker has made some changes, you can easily pull them:

git checkout foo
git pull

Response to comments:

Cool :) And if I'd like to make my own changes to that branch, should I create a second local branch "bar" from "foo" and work there instead of directly on my "foo"?

You don't need to create a new branch, even though I recommend it. You might as well commit directly to foo and have your co-worker pull your branch. But that branch already exists and your branch foo need to be setup as an upstream branch to it:

git branch --set-upstream foo colin/foo

assuming colin is your repository (a remote to your co-workers repository) defined in similar way:

git remote add colin git://path/to/colins/repo.git
rtn
  • 127,556
  • 20
  • 111
  • 121
  • 4
    That was very fast :) You might want to add that he should use the `git://` URL from the other person's GitHub repository page in the place of `//path/to/coworkers/repo.git`. (Describing that was what made my answer too slow ;)) – Mark Longair May 04 '11 at 14:20
  • Cool :) And if I'd like to make my own changes to that branch, should I create a second local branch "bar" from "foo" and work there instead of directly on my "foo"? – Colin O'Dell May 04 '11 at 14:27
  • Or is it safe to work directly in my "foo" and pull/merge his changes in later? Which is the best practice here? – Colin O'Dell May 04 '11 at 14:36
  • 2
    Nice answer in 3 minutes! – Tieme Nov 10 '14 at 11:24
  • with git version 2.19.1.windows.1 I needed to replace `git checkout --track coworker/foo` with just `git checkout foo` – Micheal Wells Jun 11 '20 at 22:30
192

The accepted answer works, but you don't need to add them as a remote, since that would be cumbersome and a pain to do each time.

Grabbing their commits:

git fetch git://path/to/coworkers/repo.git theirbranch:ournameforbranch

This creates a local branch named ournameforbranch which is exactly the same as what theirbranch was for them. For the question example, the last argument would be foo:foo.

The git://path/to/coworkers/repo.git part should be replaced with the URL on their GitHub repository page. An SSH URL would look like git@github.com:theirusername/reponame.git and an HTTPS one like https://github.com/theirusername/reponame.git.

Note :ournameforbranch part can be further left off if thinking up a name that doesn't conflict with one of your own branches is bothersome. In that case, a reference called FETCH_HEAD is available. You can git log FETCH_HEAD to see their commits then do things like cherry-picked to cherry pick their commits.

Pushing it back to them:

Oftentimes, you want to fix something of theirs and push it right back. That's possible too:

git fetch git://path/to/coworkers/repo.git theirbranch
git checkout FETCH_HEAD

# fix fix fix

git push git://path/to/coworkers/repo.git HEAD:theirbranch

If working in detached state worries you, by all means create a branch using :ournameforbranch and replace FETCH_HEAD and HEAD above with ournameforbranch.

antak
  • 19,481
  • 9
  • 72
  • 80
  • 3
    Thank you for this, the other answer does not work if both you and the other person have identically named branches (like the default `master` branch) – Job Aug 12 '17 at 15:41
  • 3
    It's worth mentioning that this method won't work if you don't have stuff like SSH key associated with your github account, see https://stackoverflow.com/questions/12940626 – Przemek D Aug 21 '17 at 08:13
  • 1
    don't you have to be added as a collaborator so you could push to their repo? – mfaani Oct 09 '17 at 22:38
  • 1
    @Honey Certainly! Pushing assumes you have the necessary permissions on the remote end to push. Fetching likewise assumes the path is accessible. – antak Oct 11 '17 at 01:27
  • If you run `git branch -m newbranch` while in this detached state, git will lose its mind and start saying your repo isn't valid anymore. `git init` seems to fix it and put you back in more or less the state you were in before, with the branch named "newbranch". – Ian Hickson Apr 30 '18 at 17:45
  • *saying your repo isn't valid anymore*: @IanHickson No, it's telling you you aren't on a branch in its own cryptic way. It's `git branch -m []` to rename a branch. Since you omitted `` you need to be on a branch for git to know what you want to rename. Not sure how `git init` managed to do the things you said as it [does practically nothing](https://stackoverflow.com/questions/5149694/does-running-git-init-twice-initialize-a-repository-or-reinitialize-an-existing). Maybe you were after `git checkout [-b] newbranch`. – antak May 02 '18 at 01:51
  • @antak I can't repro on my linux box. The issue I ran into was on a Mac, so maybe macOS has some old version of git installed with some forgotten bugs. In any case, the error message I saw was not just that I wasn't on a branch, it was "fatal: Not a git repository". Running `git init` fixed it. – Ian Hickson May 03 '18 at 02:50
  • I couldn't do the "Grabbing their commits" because I'm an utter newbie and got these errors: `The authenticity of host 'github.com (20.205.243.166)' can't be established.` and after agreeing to continue `git@github.com: Permission denied (publickey).` `fatal: Could not read from remote repository.` – hippietrail Aug 22 '22 at 09:42
  • 1
    @hippietrail I see where my answer went wrong. I've updated the answer to clarify the URL part. My previous wording directed you to use an SSH url but an HTTPS one will work in its place. You can also refer to [this answer](https://stackoverflow.com/a/12940681/1036728) for further clarification on the two types of authentication. – antak Aug 22 '22 at 10:15
  • @antak Thanks! I did find that answer after I'd already commented. Hopefully the whole thread will be easier for people who find it in the future. – hippietrail Aug 22 '22 at 11:15
31

The following is a nice expedient solution that works with GitHub for checking out the PR branch from another user's fork. You need to know the pull request ID (which GitHub displays along with the PR title).

Example:

Pull request #8
alice wants to merge 1 commit into your_repo:master from her_repo:branch

git checkout -b <branch>
git pull origin pull/8/head
  • Substitute <branch> with the branch name from her_repo:branch
  • Substitute the name of your remote if you called it something different from origin.
  • Substitute 8 with the correct pull request ID.
Subfuzion
  • 1,789
  • 20
  • 18
21

If antak's answer:

git fetch git@github.com:<THEIR USERNAME>/<REPO>.git <THEIR BRANCH>:<OUR NAME FOR BRANCH> 

gives you:

Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Then (following Przemek D's advice) use

git fetch https://github.com/<THEIR USERNAME>/<REPO>.git <THEIR BRANCH>:<OUR NAME FOR BRANCH>
Peter
  • 12,274
  • 9
  • 71
  • 86
7

Update: this no longer seems to work, as Github changed their UI, let's hope they'll restore it


GitHub has a new option relative to the preceding answers, just copy/paste the command lines from the PR:

  1. Scroll to the bottom of the PR to see the Merge or Squash and merge button
  2. Click the link on the right: view command line instructions
  3. Press the Copy icon to the right of Step 1
  4. Paste the commands in your terminal
Robert Monfera
  • 1,980
  • 1
  • 22
  • 16
6

If the forked repo is protected so you can't push directly into it, and your goal is to make changes to their foo, then you need to get their branch foo into your repo like so:

git remote add protected_repo https://github.com/theirusername/their_repo.git
git fetch protected_repo 
git checkout --no-track protected_repo/foo

Now you have a local copy of foo with no upstream associated to it. You can commit changes to it (or not) and then push your foo to your own remote repo.

git push --set-upstream origin foo

Now foo is in your repo on GitHub and your local foo is tracking it. If they continue to make changes to foo you can fetch theirs and merge into your foo.

git checkout foo 
git fetch protected_repo
git merge protected_repo/foo
J Smith
  • 181
  • 1
  • 5
-1

git fetch upstream pull/<pr_number>/head:<your_local_branch_name>

raghava
  • 24
  • 3