Skip to content

Instantly share code, notes, and snippets.

@gnarf
Last active April 12, 2024 22:00
Show Gist options
  • Save gnarf/5406589 to your computer and use it in GitHub Desktop.
Save gnarf/5406589 to your computer and use it in GitHub Desktop.
git pr - Global .gitconfig aliases for Pull Request Managment

Install

Either copy the aliases from the .gitconfig or run the commands in add-pr-alias.sh

Usage

Easily checkout local copies of pull requests from remotes:

  • git pr 4 - creates local branch pr/4 from the github upstream(if it exists) or origin remote and checks it out
  • git pr 4 someremote - creates local branch pr/4 from someremote remote and checks it out
  • git pr-clean - removes all pr/* branches from your local repo
  • git spr - Same as git pr command, but for bitbucket/stash remotes
# for github remotes
[alias]
pr = "!f() { git fetch -fu ${2:-$(git remote |grep ^upstream || echo origin)} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f"
pr-clean = "!git for-each-ref refs/heads/pr/* --format='%(refname)' | while read ref ; do branch=${ref#refs/heads/} ; git branch -D $branch ; done"
# for bitbucket/stash remotes
spr = "!f() { git fetch -fu ${2:-$(git remote |grep ^upstream || echo origin)} refs/pull-requests/$1/from:pr/$1 && git checkout pr/$1; }; f"
#!/bin/sh
# For github
git config --global alias.pr '!f() { git fetch -fu ${2:-$(git remote |grep ^upstream || echo origin)} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f'
git config --global alias.pr-clean '!git for-each-ref refs/heads/pr/* --format="%(refname)" | while read ref ; do branch=${ref#refs/heads/} ; git branch -D $branch ; done'
# For stash/bitbucket
git config --global alias.spr '!f() { git fetch -fu ${2:-$(git remote |grep ^upstream || echo origin)} refs/pull-requests/$1/from:pr/$1 && git checkout pr/$1; }; f'
@tzz
Copy link

tzz commented Jan 6, 2014

nice, thanks!

@rstacruz
Copy link

I've combined @whit537 and @andreineculau's suggestions:

[alias]
pr  = "!f() { git fetch -fu ${2:-origin} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f"

...now you can do git pr 482 upstream and switch to that branch immediately.

@gnarf
Copy link
Author

gnarf commented Aug 26, 2014

@rstacruz - cheers - updated the gist to reflect your version, I like the bash defaulting - neat trick I always forget I can use :)

@rstacruz
Copy link

rstacruz commented Oct 7, 2014

Hey @gnarf, I've opened a pr for this in git-extras: tj/git-extras#262

@gsemet
Copy link

gsemet commented Jun 29, 2016

So cool !

@bdowling
Copy link

Building on the building (and lazy defaults), since a lot of people use an upstream remote and that's where PRs are often worked... :)

pr  = "!f() { git fetch -fu ${2:-$(git remote |grep ^upstream || echo origin)} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f"

@gnarf
Copy link
Author

gnarf commented Feb 17, 2017

@bdowling makes sense!

@vagkosFoundry
Copy link

thanks!!

@Gcaufy
Copy link

Gcaufy commented Dec 25, 2017

If I checkout a pr, and I want to modified it, and then push it back to wait pr author to review it.
How can I do that?

@mokagio
Copy link

mokagio commented Jan 31, 2019

https://github.com/github/hub is also pretty cool to manage PRs from the command line.

$ hub pr --help

Usage: hub pr list [-s <STATE>] [-h <HEAD>] [-b <BASE>] [-o <SORT_KEY> [-^]] [-f <FORMAT>] [-L <LIMIT>]
       hub pr checkout <PR-NUMBER> [<BRANCH>]

I use this alias to checkout a PR by number

alias cpr='hub pr checkout' # usage `cpr <PR id>`

@kwk
Copy link

kwk commented Mar 29, 2019

I wonder if git pr 123 remotename should create pr/remotename/123 instead of pr/123. My current situation is that I have a PR to some project and somebody had a PR for my PR.

@intelfx
Copy link

intelfx commented Apr 12, 2024

There is a better way to write git pr-clean:

[alias]
	pr-clean = "!git for-each-ref --format 'delete %(refname)' 'refs/heads/pr/**' | git update-ref --stdin"

I can also offer an overengineered improved version of git pr with better logic for remote name autodetection (useful for me because I hate when my tools don't handle corner cases well) and incorporating @kwk's suggestion:

[alias]
	# includes heuristics for `git-hub` and `gh`
	zz-guess-upstream = "!f() { \
		for u; do \
			[[ $u != -* ]] && git config \"remote.$u.url\" &>/dev/null && echo \"$u\" && return; \
		done; \
		git config hub.upstreamremote && return; \
		while IFS='' read -r u; do \
			[[ \"$(git config \"remote.$u.gh-resolved\")\" == base ]] && echo \"$u\" && return; \
		done < <(git remote); \
		for u in upstream origin; do \
			git config \"remote.$u.url\" &>/dev/null && echo \"$u\" && return; \
		done; \
		return 1; \
	}; f"
	pr = "!f() { \
		remote=\"$(git zz-guess-upstream \"${@:2:1}\")\" || return; \
		prefix=\"pr${2:+\"/$2\"}\"; \
		git fetch -fu \"$r\" \"refs/pull/$1/head:$prefix/$1\" || return; \
		git checkout \"$prefix/$1\"; \
	}; f"
	pr-clean = "!f() { \
		[[ ${1+set} ]] && glob=\"$1/*\" || glob=\"**\"; \
		git for-each-ref --format 'delete %(refname)' \"refs/heads/pr/$glob\" \
		| tee /dev/stderr \
		| git update-ref --stdin; \
	}; f"

(src: https://github.com/intelfx/dotfiles/blob/4dcc85171ae91d23f704d0ac7acdecaeed536cc6/.gitconfig#L73-L125)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment