Improve Your Git Workflow With Github Hub

Janne Kemppainen |

GitHub is an essential part of development for many software projects and it has a pretty good user experience on the website. However, sometimes you just want to do things from the command line. This is where the hub utility program comes in handy.

GitHub Hub is a small helper tool that lets you manage many of the GitHub features, such as opening pull requests, creating repositories, etc., straight from the command line. In this post I will show you most of the key features, and I've added some command aliases that should make your experience with hub even better.

For this post I assume that you have set up SSH keys for GitHub.

Installation

Mac OS

The easiest way is to install with Homebrew.

>> brew install hub

Linux

You can try installing the hub package from the package manager of your distro, or use the same method as with the Windows Subsystem for Linux Ubuntu.

Windows Subsystem for Linux

At first it seemed that the best way for WSL would to be to install from source as the hub package wasn't available from apt. However, I had some problems with the Go paths and the installation script didn't seem to find any of the Go libraries so I decided to choose an alternative route.

Homebrew has a Linux counterpart called Linuxbrew which also works for WSL and the hub package is available there so this seems to be the easiest way for WSL. First make sure that you've got all the dependencies for Linuxbrew installed:

>> sudo apt-get install build-essential curl file git

Then install Linuxbrew with the command from the Homebrew on Linux page:

>> sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

Finalize the installation by adding brew to PATH and to the shell profile:

>> test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
>> test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
>> test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
>> echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile

Now you can install hub:

>> brew install hub

Hub lets you open web pages directly from the command line so you need to set the $BROWSER environment variable for it to know what browser to use. Edit your .bashrc file

>> nano ~/.bashrc

and add the following line:

export BROWSER='/mnt/c/Windows/explorer.exe'

This sets the explorer.exe as the default browser which will then direct to your Windows system default browser such as Chrome or Firefox.

Cloning repositories

You can clone existing repositores by their names. You don't need to include the username when cloning your own repositories:

>> hub clone myproject
Cloning into 'myproject'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 18 (delta 1), reused 17 (delta 0), pack-reused 0
Receiving objects: 100% (18/18), done.
Resolving deltas: 100% (1/1), done.

but you need to give the full name when using a repository from an organization or another user:

>> hub clone pakstech/twitter-followers
Cloning into 'twitter-followers'...
remote: Enumerating objects: 32, done.
remote: Counting objects: 100% (32/32), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 32 (delta 9), reused 29 (delta 6), pack-reused 0
Receiving objects: 100% (32/32), 170.84 KiB | 813.00 KiB/s, done.

Opening in a browser

If you are inside a Git repository you can open the GitHub page of your project:

>> hub browse

This uses the $BROWSER environment variable to choose which browser should be used.

Instead of opening the browser you can also print the URL with the -u or --url flag or copy to the clipboard with -c or --copy. For copying you'll need to install xclip (sudo apt install xclip, etc.).

The hub browse command takes two (optional) positional parameters: the repository and the subpage. If I want to go to the pull requests page of my twitter-followers project I can get there with this command:

>> hub browse pakstech/twitter-followers pulls

And bam! I'm immediately there sorting through the PR's.

But it isn't that fun to define the name of the repository every time, right? That's why you can use double hyphens (--) as a placeholder for the repository before the subpage. Therefore if you are inside a Git repository you can go to its pull requests page with the shortened command:

>> hub browse -- pulls

To make it even easier let's create an alias for this. Edit the ~/.bashrc file and append the following line at the end

alias pulls='hub browse -- pulls'

After saving the file, restart the terminal or reload the configurations with source ~/.bashrc. Now if you are inside a GitHub project directory this is all you need to do to open the pull requests page:

>> pulls

Implementing a new feature

Let's say that you have a user story that you want to implement to your project. The first thing you need to do is to create the feature branch normally.

>> git checkout -b my_feature

We could for example want to improve the documentation in the README.md file. So after making the necessary edits you would then add, commit and push normally.

>> git add README.md
>> git commit -m "Improve documentation"
>> git push -u origin my_feature

Now you'd normally have to go to the project page on GitHub and create a new pull request from there. With Hub you can do it from the terminal:

>> hub pull-request

This opens a new text editor where you can type the title of the PR on the first line. Leave a blank line after the title and write the PR description in Markdown after that.

There is also the pr command which allows you to list or checkout pull requests. Checking out a pull request locally is quite easy:

>> hub pr list
      #5  Add new feature   enhancement
      #4  Fix nasty bug   bug
>> hub pr checkout 4
Switched to branch 'bug_fix'
Your branch is up to date with 'origin/bug_fix'.
Already up to date.

Opening an existing pull request in a browser

Unfortunately it is not possible to edit an existing pull request from the command line as of now. That feature would be really helpful as you could add reviewers and labels, or change the description later, for example. It seems that you can't open the PR page of the current branch either if it already exists (during PR creation you can use the -o flag to open in a web browser, though).

Well, at least we can do same magic of our own with the standard Unix tools to open an existing pull request:

>> hub pr list -f '%I %H%n' | grep `git rev-parse --abbrev-ref HEAD` | awk '{split($0, a); printf "pull/%s", a[1]}' | xargs hub browse --

Let me split that into pieces so that you can understand what's going on here. The first part uses the hub pr list command which lists all pull requests for the repository. The -f argument defines the output format, in this case the pull request number and the head branch separated with a single space and ending with a newline character.

The output of the previous command is piped to grep which finds the name of the current branch with git rev-parse and returns the matching line if it exists in the PR list. Then the awk command splits the result by whitespace and selects the first element (the PR number) and prints in the format ‘pull/{number}'.

Finally the result, for example pull/1, is given as the last parameter to the hub browse command with xargs. The final result of the command will therefore be something like hub browse -- pull/1. Add this as an alias to your ~./bashrc file:

alias pull=OpenPullRequestPage
function OpenPullRequestPage()
{
  hub pr list -f '%I %H%n' | grep `git rev-parse --abbrev-ref HEAD` | awk '{split($0, a); printf "pull/%s", a[1]}' | xargs hub browse --
}

After sourcing the bash configurations you can now use pull to open the PR of the current branch! If you haven't created a PR yet or if you are on the master branch then it will just open the project page which is a graceful fallback.

GitHub releases

GitHub releases are Git tags that contain additional information such as release notes and perhaps other assets such as compiled executables. You can create a new release with:

>> hub release create v1.0

A text editor window will open. Add the title and description as you would for a pull request. After saving Hub will create the release on GitHub with the tag that was specified, in this case v1.0.

When you have releases in your GitHub repository you can list them all simply with

>> hub release

If there are lots and lots of releases in your repository you can limit the returned amount with the -L option.

You can also check the release notes for a specific tag:

>> hub release show v1.0
This is the initial release

This release has many useful things, and it can be edited

Editing an existing release is also possible with the hub release edit command. Just give the Git tag as a parameter and the text editor will open letting you change the release description.

I also came up with some Bash aliases for working with release drafts. You can add them to your Bash configurations if you find them useful.

alias list-drafts="hub release --include-drafts -f '%S %T %t%n' | grep -e '^draft'"
alias draft-release='hub release create --draft'
alias publish-release='hub release edit -m "" --draft=false'

This adds three new commands for managing releases. The first one is for listing all releases that are still drafts. Type draft-list and their tags and names will be listed.

>> list-drafts
draft v1.3 This is some feature

To create a new draft use the draft-release alias and give the desired version tag as a parameter.

>> draft-release v1.3

Edit the release notes and save. The release will be shown as a draft on the GitHub page. Finally, you can publish the draft as a release:

>> publish-release v1.3

The empty string parameter -m "" in the alias instructs hub release edit to use the existing message so the text editor won't open.

Comparing changes

When you are on a feature branch you can compare the changes against the master branch without defining any parameters:

>> hub compare

The comparison page will open on a new browser tab.

To compare the changes between releases give the desired tags separated by two or three dots:

>> hub compare v1.0..v1.1

In addition to tags, branch names and commit SHAs are also valid range parameters. The end range defaults to the current branch name if it is omitted.

Working with GitHub Enterprise

You might be working in a company where the code is hosted on a separate GitHub Enterprise installation. Hub works with GHE too but requires configurations first. You need to add your GitHub Enterprise host to the hub whitelist in git configurations, for example:

>> git config --global --add hub.host github.example.com

Now the hub commands work the same way for GHE repositories. The init and clone commands need to know which GitHub to use so you can specify the GITHUB_HOST environment variable.

>> GITHUB_HOST=git.example.com hub clone username/repository

The documentation says that Hub defaults to github.com but for me it asks which one to use if I don't specify the selection with the environment variable.

Conclusion

Hopefully this was helpful to you and you learned something new. You can read more about the available commands from the hub manual.

Discuss on Twitter

Subscribe to my newsletter

What's new with PäksTech? Subscribe to receive occasional emails where I will sum up stuff that has happened at the blog and what may be coming next.

powered by TinyLetter | Privacy Policy