Hugo development - how to contribute code

I’ve found it really odd working on Hugo. I’ve had a lot of help from @bep and Google, but it seems like every time I take a break, I have to relearn a lot of tiny steps. This post captures some of the knowledge. I’d like to get feedback from the developers so that I can turn this into a page for the Hugo docs.


Working with hugo, hub, git, and go

The big picture seems pretty clear: get a GitHub account, fork spf13/hugo, make changes, test changes, create a pull request, then bask in the glory of a job well done.

Hugo has a lot of pieces, so there’s some work that you’ll need to do in order to work on it.

Install Go

The best instructions for installing and setting up Go are at https://golang.org/doc/install. You must set and export the GO variables as explained on the Go site.

I use a Mac, so the natural place for my Go files was ~/Software/go. On a Linux system, you’d probably place it in ~/go. The location isn’t important, but you must remember to use your location in all the commands, not the location from the examples.

Speaking of an example, on my Mac, I added commands to my ~/.bash_profile so that my Go environment is set up automatically every time I open a new terminal window.

$ cat ~/.bash_profile
export GOPATH=$HOME/Software/go
PATH=$GOPATH/bin:$PATH
alias cdhugo='cd $GOPATH/src/github.com/spf13/hugo'

After doing so, I can open a new terminal window and confirm my GOPATH setting like so:

$ env | grep GO
GOPATH=/Users/mdhender/Software/go

Note that I also added a cdhugo command to make it easy to change to the Hugo source directory.

Create an account on GitHub

If you’re going to contribute code, you’ll need to have an account on GitHub. Go to https://github.com/join and set up a personal account.

Install git on your system

You will need to install git and learn how to use it. I’m on a Mac, so I installed using the brew command. I also installed a helper tool, hub, because it makes some things simpler.

TODO: Windows/Linux

Git Graphical Front Ends

I like using the GUIs (SourceTree, Tower), but it seems like I still have to go to the command line to keep things going.

Install hub on your system

Hub is a great tool for working with GitHub. The main site for it is https://hub.github.com/. We’re assuming that you’ll install it, too. If not, you’ll need to translate to the appropriate git + GitHub commands.

On a Mac, install using brew:

$ brew install hub

And create an alias so that typing git actually runs hub:

$ echo "alias git='hub'" >> ~/.bash_profile

Open up a new terminal window and confirm the installation:

Confirm the installation:

$ git version
git version 2.6.3
hub version 2.2.2

Create your Working Copy

The working copy is on your computer. It’s what you’ll edit, compile, and end up pushing back to GitHub.

The main steps are cloning the repository and creating your fork as a remote.

Clone the Repository

Assuming that you’ve set up your GOPATH (see the section above if you’re unsure about this), you should now copy the Hugo repository down to your computer. You’ll hear this called “clone the repo,” so if you have any issues with this step, Google that phrase.

We’re going to clone the master Hugo repository. That seems counter-intuitive, since you won’t have commit rights on it, but it is needed for the Go workflow. You’ll work on a copy of the master and push your changes to your repository on GitHub.

So, let’s clone that master repository:

$ go get -v -u github.com/spf13/hugo

Note that the main installation document for Hugo says that "you may run go get with the -u option to update Hugo’s dependencies. The clue is that you’ll get odd errors when compiling. When you do, run go get -v -u github.com/spf13/hugo to synch up those dependencies.

TODO: is there a better way to phrase this?

Fork the Repository

Hub makes forking a repository really easy:

$ git fork

That command will log in to GitHub using your account, create a fork of the repository that you’re currently working in, and add it as a remote to your working copy. You can confirm that with:

$ git remote -v
mdhender	git@github.com:mdhender/hugo.git (fetch)
mdhender	git@github.com:mdhender/hugo.git (push)
origin	https://github.com/spf13/hugo (fetch)
origin	https://github.com/spf13/hugo (push)

The Hugo Development Workflow

Create a Branch

You should never develop against the “master” branch because the development team will not accept a pull request against that branch. Instead, create a named branch and work on it.

$ git checkout -b enh/1718-integrate-textql

Coding

Once you’ve done that, you can start developing.

TODO: Testing

Formatting

Please run go fmt before committing to make sure that your code is formatted properly.

TODO: Squashing Commits

TODO: Pull Request

The hub tool has a super-easy interface for creating pull requests.

$ git push mdhender enh/1718-integrate-textql
$ git pull-request --browse

TODO: Synching back up with spf13/hugo

Notes

Build and Install from the root directory

It seems obvious. Another good reason for using an IDE.

Accept the learning curve

It will become a habit, eventually.

The take-away from this is, after you’ve done your setting up, the workflow from the command line is:

$ git checkout -b _your_branch_name_
# code
# test
# format
$ gofmt
$ git push _your_github_username_ _your_branch_name_
$ git pull-request --browse
1 Like

I have made an enormous amounts of pull requests for different projects the last year, some of them Go projects, some not. But the work flow that works for both of them is (the example below is for Hugo, a go project):

  1. Install https://hub.github.com/
  2. go get -u -v github.com/spf13/hugo
  3. cd $GOPATH/src/github.com/spf13/hugo/
  4. checkout -b my-fix-branch
  5. Do the coding. When done:
  6. hub fork
  7. git push <your-github-username> my-fix-branch
  8. hub pull-request

The work flow above is so cheap that even small theme edits is something I bother to do.

Disclaimer: The above is typed from memory, but I have done it so many times, so it should be correct.

For non-go-projects, you would do a git clone instead of the go get.

3 Likes