Git Workflows - Geosyntec/pygridtools GitHub Wiki

Working with source code

Thing you only do once

pygridtools uses git to manage its source code and releases. Here's what you need to know to get started.

Install git.

The official binary installers for the Windows versions of git are here: Git for Windows.

When you install it will ask you about line endings. I can't remember which option, as the installation UI explains them, is the right one. Stick with the default and we'll fix it when we configure git below.

Configure git

Git's configuration is stored in a file called .gitconfig that typically lives in your $HOME directory (e.g., C:\Users\phobson). You can edit that file directly with at least these options (adapted for your info, of course):

        name = Paul Hobson
        email = [email protected]  # +git help you filter email notifications

        autocrlf = true
        editor = vim  # !!! change or remove this if you don't love vim or know what it is

        summary = true

        lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative

Alternatively (if you can't find .gitconfig, you can set these options from the command line. If you do that, they're sticky (meaning you only have to do it once).

So from git terminal you installed, you would do:

$ git config --global "Paul Hobson"
$ git config --global [email protected]
$ git config --global core.autocrlf true
$ git config --global core.editor vim # !!! remove this if you're not sure about vim
$ git config --global merge.summary true
$ git config --global alias.lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative

Configure SSH

This is a slightly more complicated topic. In the interest of time, I'll defer to the GitHub docs for now. As y'all work through that, we can add detail here to clear up friction points.

Create your own fork.

The basic tenant of this git workflow that I want to drive home is this: Never add commits to Geosyntec/pygridtools/master directly. "What's master?" you might ask. We'll get there.

For now: just know that you never add or remove code directly from the "master" (read: central, main, production, whatever) code. Instead, you work in a little sandbox that git creates and then use the GitHub UI to ask for peer review and then incorporate into the main code base.

The first step in this is creating a "fork" of Geosyntec/pygridtools repository. To do that, navigate in a web browser to Geosyntec/pygridtools and click the "fork" button.

Clone your fork of pygridtools to your desktop

Now it's time for me to clone the source code to my desktop. I'll open up a terminal and navigate to a directory where I like to keep source code:

$ cd C:\users\phobson\sources\misc

Now, using the SSH URL, I'll clone the source code into a new folder within that directory:

$ git clone [email protected]:phobson/pygridtools.git

Git will magically grab all of the source code and its history. If you navigate into the source directory now, you verify the origin of the clone:

$ git remote -v
origin  [email protected]:phobson/pygridtools.git (fetch)

Here, "origin" is the name of the remote (repository). You can have as many remote repositories (pointing to different forks) as you want. By convention, we should add an "upstream" that points to the central/production repo.

$ git remote add upstream [email protected]:Geosytnec/pygridtools.git

Phew. We're done setting up. Now let's get to work.

Things you do a lot

Add, change, or remove code (basically work)

If your terminal is still in the source directory, you can check it's stats with:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

Let me stress this again never make changes to master, even your fork of master.

Create a new branch

When using git collaboratively, you should always work in a branch that is based off of master.

$ git branch add-animations  # create the branch
$ git checkout add-animations # switch to the branch
Switched to branch 'add-animations'

Alternatively, you can combine those two commands with the -b option:

$ git checkout -b add-animations
Switched to a new branch 'add-animations'

Make changes to the source directory

At this point we can use git checkout to switch between any existing branch. But since we're on add-animations, let's do some work and add my javascript code that creates animations.

(opens text editor, bumps, knocks, kitchen pans falling on the grounds)

OK, I created, edited, and saved a file, plus changed an existing file. Let's check the status of the branch:

$ git status
On branch from-generic-data
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   existing_dir/existing_file.html

Untracked files:
  (use "git add <file>..." to include in what will be committed)


I can look at those changes with git diff, but I'm not going to show that output. Just know that you can.

So now we need to add the changes to the staging area:

$ git add existing_dir/existing_file.html viz/swarm.js

Let's check the status again:

$ git status
On branch from-generic-data
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   viz/swarm.js
        modified:   existing_dir/existing_file.html

Now we're ready to "commit" those changes to the add-animations branch. Every commit has to include a messages describing it. You could theoretically punt a bunch of garbage in that message. However, if you do that, and I'm reviewing your work, I will not accept it without good commit messages.

Good commit message:

Revised animation package algorithm to be have an adaptive frame rate

Bad commit message:

animation package changes

If you can fit that message into about 80 characters (one line), you can commit and add the message like this:

$ git commit -m "Revised animation package algorithm to be have an adaptive frame rate"

If you need more room to type (multiple lines) simply do:

$ git commit

This will open your text editor. Type away, save, and close your text file.

At this point, you can continue to make changes and create new commits. Eventually, the code will be ready for review and incorporation into the main code base. To push the code to your fork on gitlab, do:

$ git push origin add-animations

Remember, "origin" is the remote name of your fork.

Now go to Geosyntec/pygridtools and create a pull request.

This confusing, but the "Source Branch" if the pull request UI is where you want the code to go (the main repo i.e., Geosyntec/pygridtools, master). The Target Branch is where your changes already exist -- phobson/pygridtools, add-animations. The physical analogy here is that we're in the master copy of the code and using a grappling hook to pull the changes towards us. So in that sense, the "Target" is where we throw the hook and not the destination.

As you create the merge reguest, assign someone to review your code. They may or may not request chances. If the do, you can add and push commits to your existing branch as we did before. The pull request will update as you push. Eventually, everyone is happy and the reviewer will merge your changes 🎉

When that happens, delete the copy of the branch from the pull request page.

Syncing your clone with "upstream"

So your pull request was accepted and pulled into Geosyntec/pygridtools master. Nice work. While you were implementing animations, lots of other things were happening in other parts of the code. So now we need to sync up our local copy with Geosyntec/pygridtools master before we can start work on the next big thing.

At a bare minimum, we fetch the latest code and do a "fast-foward" (ff) merge into our existing repo:

$ git checkout master  # switch to your master branch
$ git fetch upstream   # get the latest from upstream
$ git merge --ff-only upstream/master # upstream = Geosyntec/pygridtools

From there it's good to push those changes back to your fork. Strictly speaking, this isn't required. But it's quick and easy so why not?

$ git push origin master

From there we can go ahead and make a new branch and get to work.

House keeping

After a while you start to accumulate a lot of branches. If you deleted the remote version of them when the pull requests were accepted (like I said you should), you can do:

$ git remote prune origin

Git will then print a list of all of the branches that were merged into upstream/master.

Now you can delete them locally with:

$ git branch -d deleted-branch1 second-deleted-branch deleted-branch-C

Having trouble?

I need to "rebase", what's that?

Call Paul: x5905

I rebased and now have merge conflicts!

Call Paul: x5905

I committed against master

I told you not to do that. Call Paul: x5905


Call Paul: x5905

⚠️ ** Fallback** ⚠️