Use Case

I have forked a repo, I’ve made some changes and my fork and upstream diverged.

In the meantime someone sent a PR to upstream and this PR is still open or rejected/closed etc by maintainers. However I’d like to apply the changes that PR proposes into my fork.

Solutions

One Time

If this is a one time thing, then you can get with fetch:

$ git fetch upstream pull/42/head

Then you can merge, cherry-pick etc. these PR changes.

Or you can pull directly:

$ git pull upstream pull/42/head

Info

As you may see, above scripts assumes your remote upstream repo named upstream and 42 is the PR number you’d like to apply, change them accordingly.

Git Alias

If you regularly will apply PRs then you can add related functions as aliases in your local or global config, a.k.a one of the below:

  • ${YOUR_REPO}/.git/config (local)
  • ~/.gitconfig (global)
  • ${XDG_CONFIG_HOME}/git/config (global)
# ${REPO}/.git/config
# ~/.gitconfig
# ${XDG_CONFIG_HOME}/git/config
[alias]
    gfpr = "!f() { git fetch upstream refs/pull/$1/head:pr/$1; } ; f"
    gppr = "!f() { git pull upstream pull/$1/head; } ; f"

Then fetch all PRs.

$ git fetch upstream

To check out a particular PR #42:

$ git checkout pr/42
Branch pr/42 set up to track remote branch pr/42 from upstream.
Switched to a new branch 'pr/42'

Local gitconfig

You can append fetch config in your local config.

1
2
3
4
5
# .git/config
[remote "upstream"]
	fetch = +refs/heads/*:refs/remotes/origin/*
	url = [email protected]:joyent/node.git
	fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

The rest is the same as above.

With Script

You can append above related fetch config with below script:

#!/usr/bin/env bash

git remote -v | grep fetch | grep github | \
    while read remote url _; do
        if ! git config --get-all "remote.$remote.fetch" | grep -q refs/pull
        then
            git config --add "remote.$remote.fetch" \
                '+refs/pull/*/head:refs/remotes/'"$remote"'/pull/*'
        fi
    done

The rest is the same.

All done!

Resources: