├── LICENSE ├── gh-branch └── readme.md /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /gh-branch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | help() { 5 | cat <&2 30 | exit 1 31 | ;; 32 | esac 33 | shift 34 | done 35 | 36 | branch_info() { 37 | git for-each-ref 'refs/heads/**' --format='%(refname:short)%09%(committerdate:unix)%09%(committerdate:relative)%09%(HEAD)' 38 | } 39 | 40 | list_prs() { 41 | gh api graphql --cache=5m -F owner='{owner}' -F repo='{repo}' -f query=' 42 | query ($owner: String!, $repo: String!) { 43 | repository(owner: $owner, name: $repo) { 44 | pullRequests(last: 100) { 45 | nodes { 46 | number 47 | author { 48 | login 49 | } 50 | state 51 | headRefName 52 | } 53 | } 54 | } 55 | } 56 | ' --template ' 57 | {{- range .data.repository.pullRequests.nodes -}} 58 | {{- .headRefName | printf "%s\t" -}} 59 | {{- $stateColor := "green" -}} 60 | {{- if eq .state "CLOSED" }}{{ $stateColor = "red" }} 61 | {{- else if eq .state "MERGED" }}{{ $stateColor = "magenta" }}{{ end -}} 62 | {{- .number | printf "#%.0f" | color $stateColor -}} 63 | {{- .author.login | printf " by %s\n" -}} 64 | {{- end -}} 65 | ' 66 | } 67 | 68 | find_pr() { 69 | local head_branch rest 70 | while IFS=$'\t' read -r head_branch rest; do 71 | if [ "$1" = "$head_branch" ]; then 72 | printf "\t%s" "$rest" 73 | break 74 | fi 75 | done 76 | } 77 | 78 | render() { 79 | local branches branch timeago current all_prs 80 | branches="$(branch_info)" || return 1 81 | all_prs="$(list_prs 2>/dev/null || true)" 82 | sort -k2 -r <<<"$branches" | while IFS=$'\t' read -r branch _ timeago current _; do 83 | [ "$current" = "*" ] && continue 84 | printf "%s\t%s%s\n" "$branch" "$timeago" "$(find_pr "$branch" <<<"$all_prs")" 85 | done | tableize 86 | } 87 | 88 | tableize() { 89 | column -t -s$'\t' 90 | } 91 | 92 | if [ -n "$static" ]; then 93 | render 94 | exit 0 95 | fi 96 | 97 | if ! type -p fzf >/dev/null; then 98 | echo "error: install \`fzf\` to use this command" >&2 99 | exit 1 100 | fi 101 | 102 | choose() { 103 | local rendered 104 | rendered="$(render)" || return 1 105 | #--multi --bind "ctrl-d:execute-silent(git branch -D {+1})+reload(\"$0\" --static)" 106 | fzf --ansi <<<"$rendered" 107 | } 108 | 109 | selected="$(choose)" 110 | [ -n "$selected" ] || exit 1 111 | git checkout "${selected%% *}" 112 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # `gh branch` GitHub CLI extension 2 | 3 | [GitHub CLI](https://github.com/cli/cli) extension for fuzzy finding, quickly switching between, and deleting branches. 4 | 5 | ## Installation 6 | ``` 7 | gh extension install mislav/gh-branch 8 | ``` 9 | 10 | This extension depends on [fzf](https://github.com/junegunn/fzf#readme) as a fuzzy finder. To install using Homebrew: 11 | ``` 12 | brew install fzf 13 | ``` 14 | 15 | See the fzf documentation for details on installing on [Windows](https://github.com/junegunn/fzf#windows) and [Linux](https://github.com/junegunn/fzf#using-linux-package-managers) 16 | 17 | ## Usage 18 | ``` 19 | gh branch 20 | ``` 21 | 22 | Displays an interactive branch switcher that lists local branches in relation 23 | to the pull requests in the repository. The selected branch is checked out. 24 | 25 | 26 | --------------------------------------------------------------------------------