loading...

Open the GitHub project page of a repo from Terminal

shayde profile image Shayde Nofziger ・2 min read

I find myself frequently needing to go to the homepage of the projects I contribute to on GitHub. I have bookmarked the important ones, and a quick Google search of the project name and "github.com" should take me to the right place, but that can be time-consuming and requires a non-negligible amount of context switching. I decided to automate this process so as to not interrupt my workflow.

To do so, I wrote up a quick bash function to perform the automation, placed it in my .bashrc file, and assigned it to the alias github:

alias github=GitHub

function GitHub()
{
    if [ ! -d .git ] ; 
        then echo "ERROR: This isnt a git directory" && return false; 
    fi
    git_url=`git config --get remote.origin.url`
    if [[ $git_url != https://github* ]] ;
        then echo "ERROR: Remote origin is invalid" && return false;
    fi
    url=${git_url%.git}
    open $url
}

Here's what that code is doing, in layman's terms:

  • First, we check to see if we are at the root of a git repository by checking for the existence of a .git/ directory.
  • Next, we get the remote.origin.url property from the git config. This is the URL of the remote git repo with which the project is associated. For GitHub projects, this takes the form: https://github.com/[USERNAME]/[PROJECT_NAME].git
  • If the remote.origin.url is not from GitHub, we can't guarantee our ability to open it, and throw an error.
  • Finally, we remove .git from the URL and use the open command in macOS to open a browser at that given URL.

Now, any time I'm in the base directory of a project cloned from GitHub, I can open its project page straight from Terminal by running github.

This is my first time really exploring the power of incorporating bash functions and aliases into my workflow. I'm now actively looking out for tasks I perform regularly that could be automated, and will try to create bash functions for them as needed.

This code snippet and another I've created to get the size of the working directory are on GitHub, and I plan to publish all the future ones I create as well! Feel free to contribute and share your own!

Some questions to inspire discussion:

  • What actions do developers perform regularly that could benefit from automation?

  • Have you used bash functions to automate your workflow? If so, feel free to share examples so others may learn! If not, could you see yourself using them in the future?

Discussion

pic
Editor guide
Collapse
tyrelsouza profile image
Tyrel Souza

I use the ssh format for adding my remotes, this only seems to pick up http urls.

I hastily redid an else condition that will work with git@github.com: remotes as well.

function GitHub()
{
    if [ ! -d .git ] ;
        then echo "ERROR: This isnt a git directory" && return false;
    fi
    git_url=`git config --get remote.origin.url`
    if [[ $git_url == https://github* ]];
    then
        url=${git_url%.git}
    else
       if [[ $git_url == git@github.com* ]]
       then
            url="https://github.com/${${git_url:15}%.git}"
       else
           echo "ERROR: Remote origin is invalid" && return false;
       fi
    fi
    open $url
}
Collapse
frailwords profile image
Sriram Viswanathan

Just a small & quick modification to add current branch & non-github domain -

alias github=GitHub

function GitHub()
{
    if [ ! -d .git ] ;
        then echo "ERROR: This isnt a git directory" && return false;
    fi

    git_url=`git config --get remote.origin.url`
    git_domain=`echo $git_url | awk -v FS="(@|:)" '{print $2}'`
    git_branch=`git rev-parse --abbrev-ref HEAD 2>/dev/null`

    if [[ $git_url == https://* ]];
    then
        url=${git_domain}/${git_url%.git}/tree/${git_branch}
    else
       if [[ $git_url == git@* ]]
       then
            url="https://${git_domain}/${${git_url#*:}%.git}/tree/${git_branch}"
            echo $url
       else
           echo "ERROR: Remote origin is invalid" && return false;
       fi
    fi
    open $url
}

Collapse
engineercoding profile image
Wesley Ameling

The version for Git Bash (windows). It replaces the open command and for some reason it cannot parse a nested variable modification (line 17)

function GitHub()
{
    if [ ! -d .git ] ;
        then echo "ERROR: This isnt a git directory" && return false;
    fi

    git_url=`git config --get remote.origin.url`
    git_domain=`echo $git_url | awk -v FS="(@|:)" '{print $2}'`
    git_branch=`git rev-parse --abbrev-ref HEAD 2>/dev/null`

    if [[ $git_url == https://* ]];
    then
        url=${git_domain}/${git_url%.git}/tree/${git_branch}
    else
       if [[ $git_url == git@* ]]
       then
            cut_off=${git_url#*:}
            url=https://${git_domain}/${cut_off%.git}/tree/${git_branch}
       else
           echo "ERROR: Remote origin is invalid" && return false;
       fi
    fi
    explorer $url
}
Collapse
n1amr profile image
Amr Alaa
git config --global alias.go "!f() { git-browse $*; }; f"

.../bin/git-browse

#!/bin/bash

action=''
remote_name=origin

while [ $# != 0 ]; do
    case $1 in
        -r)
        [[ $# < 2 ]] && echo "Error: No remote name" && exit 1
        remote_name="$2"
        shift
        ;;

        *)
        if [[ -n "$action" ]]; then
            echo "Only one action is required."
            exit 1
        fi
        action="$1"
        ;;
    esac
    shift
done

if ! git rev-parse 1>/dev/null 2>&1; then
    echo "ERROR: This isnt a git directory"
    exit 1
fi

git_url="$(git config --get remote.${remote_name}.url)"
git_url=${git_url%.git}

git_protocol="$(echo "$git_url" | awk -v FS="(@|:)" '{print $1}')"
if [[ "$git_protocol" == 'http' ]] || [[ "$git_protocol" == 'https' ]]; then
    git_domain="$(echo "$git_url" | awk -F'/' '{print $3}')"
    git_url="$git_url"
elif [[ $git_protocol == 'git' ]]; then
    git_url="${git_url#*@}"
    git_domain="$(echo "$git_url" | awk -F':' '{print $1}')"
    git_url="https://${git_url/:/\/}"
elif [[ "$git_protocol" == 'github' ]] || [[ "$git_protocol" == 'gitlab' ]]; then
    git_domain="${git_protocol}.com"
    git_url="https://${git_protocol}.com/${git_url#*:}"
else
    echo "ERROR: Remote $remote_name is invalid"
    exit 1
fi
url="${git_url}"

git_branch="$(git rev-parse --abbrev-ref HEAD 2> /dev/null)" || git_branch=''

case "$action" in
    '') action='home' ;;
    '-') action='current' ;;
    b) action='branches' ;;
    i) action='issues' ;;
    r) action='releases' ;;
    s) action='settings' ;;
    t) action='tags' ;;
    w) action='wiki' ;;
esac

case "$action" in
    'home') url="$url" ;;
    'branches') url="$url/branches" ;;
    'issues') url="$url/issues" ;;
    'releases') url="$url/releases" ;;
    'tags') url="$url/tags" ;;
    'repo-settings') url="$url/settings/repository" ;;

    'current')
        if [[ -z "$git_branch" ]]; then
            echo "Error: No branch"
            exit 1
        fi
        url="$url/tree/${git_branch}"
    ;;

    'wiki')
        if [[ "$git_domain" == 'gitlab.com' ]]; then
            url="$url/wikis"
        else
            url="$url/wiki"
        fi
    ;;

    'settings')
        if [[ "$git_domain" == 'gitlab.com' ]]; then
            url="$url/edit"
        else
            url="$url/settings"
        fi
    ;;

    *)
        echo "ERROR: Unknown action $action"
        exit 1
    ;;
esac

echo "Opening $url"
sensible-browser "$url"
Collapse
memowe_88 profile image
Mirko Westermeier

Nice!

Just for fun: do you have any idea how to add this as a hub command to git? ❤

Collapse
ikirker profile image
Ian Kirker

Just put it in a script called git-hub and add that to a directory in your path.

Thread Thread
memowe_88 profile image
Collapse
math2001 profile image
Mathieu PATUREL

Personally, I prefer this command to be associated with the hub alias, so I can just run:

git hub

And since the folder name is really often the same as the repository name, here's my solution:

git config --global alias.hub '!f () { local REPO;local URL;[[ -f .githubrepo ]] && REPO="$(head -n 1 .githubrepo)" || REPO="${PWD##*/}";URL="https://github.com/<your username>/$REPO";if [[ "$1" == i ]];then URL="$URL/issues";elif [[ "$1" == s ]];then URL="$URL/settings";elif [[ "$1" == p ]];then URL="$URL/pulls";elif [[ "$1" == w ]];then URL="$URL/wiki";elif [[ "$1" == b ]];then URL="$URL/branches";elif [[ "$1" == r ]];then URL="$URL/releases";fi;echo "Opening $URL...";start "$URL";};f'

Make sure you change <your username> to your username.

Now you can run

$ git hub -> opens the repo depending on the folder's name
$ git hub i -> opens issues/ 
$ git hub p -> opens pulls/
$ git hub s -> opens settings/
$ git hub w -> opens wiki/
$ git hub b -> opens branches/
$ git hub r -> opens releases/
$ git hub whatever -> opens whatever/

If the name of the folder doesn't correspond to the name of the repository, you can add a .githubrepo file and set its content to the name of it, and it'll use this instead.

Hopefully it'll save some people a bit of time

Collapse
bertocq profile image
BertoCQ

Cool trick :). I have a bash alias go='git browse' that does the same using hub.github.com, but having the script on the dotfiles would be handy if I'm in a computer where its not available.

Collapse
jotarios profile image
Jorge Rios

Hi guys, this my own version for ssh and https, in one line, also you can run it in a subdirectory:


bash
function GitHub()
{
    git_url=`git config --get remote.origin.url`
    url=`echo $git_url | sed -e "s/git@github.com:/https:\/\/github.com\//"`
    if [[ $url != https://github* ]] ;
        then echo "ERROR: Remote origin is invalid" && return false;
    fi
    # url=${git_url%.git}
    # Use "open $url" if you use MacOS
    # Use x-www-browser if you use GNU/Linux
    x-www-browser $url
}
Collapse
hoelzro profile image
Rob Hoelz

There's a feature in Git called insteadOf that allows you to make shorthand URLs (so you can say things like git clone me:my-project rather than git clone git@github.com:hoelzro/my-project) - git-config unfortunately doesn't handle insteadOf. If you want your function to work with these remote URLs, you can use git ls-remote --get-url origin instead.

You might also want to use the local bash builtin to introduce git_url and url as local variables to prevent your function from contaminating your bash session!

Collapse
nateowami profile image
Nathaniel Paulus

I've been using git-open and it has worked perfectly for me (even takes you to the current branch). Currently aliased to gh, though it also works with GitLab and Bitbucket.

npm install --global git-open

Bash scripts are great. Just wanted to point out there's a solid implementation of this though for those who want it.

Collapse
lordmathis profile image
Matúš Námešný

on Linux change open to xdg-open

Collapse
pschfr profile image
paul schaefer

or use sensible-browser

Collapse
jotarios profile image
Jorge Rios

or use x-www-browser in Ubuntu

Collapse
vbjelak profile image
Vladi Beeblebrox

any tip on using two or more remotes (different credentials) on the same machine.. Let's say I use GitHub, my home NAS git and company's git server on the same machine for different projects... How to switch between these fast?

tips needed :) thanks in advance

Collapse
aghost7 profile image
Jonathan Boudreau

You could just change your ssh config to use different identities based on the IP or something. If you need to use a different email, etc for certain projects you can use git config user.email 'you@email.com' (without --global) to change it from the default global configuration.

Collapse
aghost7 profile image
Jonathan Boudreau

I personally just use fugitive from VIM. If I ever need to see something from Github I just run :Gbrowse or if I want to just get the link to share it with someone I run :Gbrowse!.

Collapse
lfkwtz profile image
Michael Lefkowitz

Thanks for this. If you have GitHub Desktop installed - you may need to use a different alias.