GitHub N00b Makes Huge Edit to Juniper EZ Library

GitHub Logo

In Monday’s post about installing the Juniper EZ Python library on Ubuntu I noted a typo in the word “version” in one of the modules and casually called on author Jeremy Schulman to fix it. Jeremy had other ideas though, and in the true spirit of collaborative development, challenged me to fix it myself.

I think that is a terrific idea (wish I had thought of it, in fact) because I’ve been meaning to look at Github for a while and never quite got around to it. Plus, let’s face it, the great thing about open source development is that anybody can fix anything, isn’t it? Why should Jeremy fix minutiae like this when I could fix it, and leave him more time to work on more important things? I am empowered!

This post, then, is a quick newbie’s guide, written by a newbie (me), on how to get set up with github so that I can make my first changes to Jeremy’s Juniper EZ library project.

Creating my GitHub Account

Creating an account on GitHub.com is incredible simple (in fact, it doesn’t even ask you to repeat your password, which is slightly concerning!). When you go to github.com as an unregistered user, you will see the account creation right there on the home page; all you need is a username, an email and a password.Creating a GitHub Account

Setting Up Git

Once you’re logged in to github.com, there is help to get you started right there on the landing page in the form of the “GitHub Bootcamp”.

GitHub Bootcamp

I started with number 1, logically, and learned that Git is an open source Version Control System (VCS) around which the GitHub community and repository revolves. If you don’t have Git already installed, you’ll need to do so (and I’ll leave that process to the guides online). I have it installed now on my Mac though:

john@Mac:~/$ git --version
git version 1.8.3.4 (Apple Git-47)

Curiously, the first thing on the Set Up Git page was a suggestion to “Forget the terminal. Download our native app instead.” I followed the download link, expanded the archive to get a file called github which, when run, offers to move itself to the Applications folder. Logging in, you have a chance to configure the name and email that will be used on your code check-ins. You also get an option to install command line tools, which I chose to do.

The native (GUI) app turns out to be a rather lackluster replacement for the command line, and unless I’m missing a lot of commands somewhere, much of the process I followed had to be executed at the command line. Perhaps somebody with more experience than I can tell me if that’s a fair summary?

More Help

One of the links offered on that first help page was a crash course to learn about Git, which was equally well written and easy to follow. I found that to get things working, I had to pull a bit of information from the Bootcamp and some from the Crash Course documentation.

HTTP Proxies

Evidently Git is unable to read the proxies configured on my Mac, so I needed to manually configure Git to use a proxy. This was achieved at the command line with these commands:

git config --global http.proxy http://10.2.2.2:8080
git config --global https.proxy http://10.2.2.2:8080

Forking The Repository

In this case since I want to contribute to somebody else’s project in a polite fashion, I’m going to use the ‘fork and pull’ model of contributing, described thus in the help:

The Fork & Pull Model lets anyone fork an existing repository and push changes to their personal fork without requiring access be granted to the source repository. The changes must then be pulled into the source repository by the project maintainer. This model reduces the amount of friction for new contributors and is popular with open source projects because it allows people to work independently without upfront coordination.

That sounds perfect. It seems that in order to fork the repository, I have to go to the Github website and make the fork there as there isn’t an obvious way to do this in the GUI client. While logged in, I browsed to Jeremy’s py-jnpr-eznc project and clicked Fork.

Forking a Repository

Within a few seconds I had my own forked repository of Jeremy’s code. Why a fork? Because it keeps my changes safely isolated from the main project, and they can always be incorporated back into the main project later. Having my own copy also means that Jeremy doesn’t have to manage permissions on his project for anybody who wants to contribute, and figure out who he trusts to have access. The website shows my new (forked) project and notes where it originally came from:

GitHub Fork Origin

Initially the forked project only exists on GitHub.com, so within the native app I clicked on the “GITHUB.COM” tab then clicked on the refresh icon at the bottom. To get a copy of the repository, I selected the “Clone to computer” option, and chose a destination directory.

Cloned Library in GUI App

An alternate method would be to use the CLI; move to the parent directory in which you want the repository to live, then issue the clone command:

git clone https://github.com/jgherbert/py-junos-eznc.git

Note that I’m cloning my fork of the project, not the original project.

The documentation indicated that I should configure Git to know about Jeremy’s original project, the “upstream” repository. And so I did, again, at the command line from within the cloned repository directory:

john@Mac:~/py-junos-eznc$ git remote add upstream https://github.com/jeremyschulman/py-junos-eznc.git
john@Mac:~/py-junos-eznc$ git fetch upstream
From https://github.com/jeremyschulman/py-junos-eznc
 * [new branch]      EA_0_0_2   -> upstream/EA_0_0_2
 * [new branch]      master     -> upstream/master

The idea of configuring an “upstream” repository is that when Jeremy makes changes to his project I can get those changes easily brought over to my forked project (either updating my files automatically, or via a manual merge process).

Making The Change

In this case, I want to make a really simple change – fixing a typo I noticed in one of the modules’ outputs (“versino” instead of “version”). So let’s try making that change in my forked repository. In the shell (terminal window), I browsed to the repository and then to the directory containing the file I wanted to edit.
Here’s the line that needs the typo fixing in the file lib/jnpr/junos/facts/swver.py:

    retstr = "junos.versino_info(major={major}, type={type}, minor={minor}, build={build})".format(

I made the correction and saved:

    retstr = "junos.version_info(major={major}, type={type}, minor={minor}, build={build})".format(

Then I checked whether git would notice the change:

john@Mac:~/py-junos-eznc$ git status
# On branch master
# 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:   lib/jnpr/junos/facts/swver.py
#
no changes added to commit (use "git add" and/or "git commit -a")

Git correctly identified that the file swver.py was modified, but noted that it was not staged to be added to the repository yet, it’s still just a working file. Since that’s the extent of my edits, I’d like to be able to ‘check in’ the changes in that working file. To do that, I need to stage the change using the git add command:

john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$ git add swver.py
john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   swver.py
#
john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$

Staged files are the ones that will be added to the main repository when you do the commit. This means that you can have edited files in your working directory that are not staged for check in, so would not be committed. In the output above, Git noted that the modified swver.py will be committed. I can check the exact changes I’m about to commit with the git diff --cached command:

john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$ git diff --cached
diff --git a/lib/jnpr/junos/facts/swver.py b/lib/jnpr/junos/facts/swver.py
index 042994e..e9a033a 100644
--- a/lib/jnpr/junos/facts/swver.py
+++ b/lib/jnpr/junos/facts/swver.py
@@ -27,7 +27,7 @@ class version_info(object):
     self.as_tuple = self.major + tuple([self.minor, self.build])

   def __repr__(self):
-    retstr = "junos.versino_info(major={major}, type={type}, minor={minor}, build={build})".format(
+    retstr = "junos.version_info(major={major}, type={type}, minor={minor}, build={build})".format(
       major=self.major,
       type=self.type,
       minor=self.minor,

Reading between the lines (haha, see what I did there?) the diff output shows the code before and after the actual change, then indicates the old line (prefixed with ‘-’) and the new line (prefixed with ‘+’).

I was ready to commit my change, and in this instance I only needed a short commit message (a note indicating what’s in the commit), so I used a single command:

john@Max:~/py-junos-eznc/lib/jnpr/junos/facts$ git commit -m "Fixed typo in swver.py"
[master 954b6c5] Fixed typo in swver.py
 1 file changed, 1 insertion(+), 1 deletion(-)

And it’s committed! If you omit the -m "message" argument, git takes you into vi (or your default editor) so that you can create a commit message. Checkin the status again after the commit operation confirms that the work was completed:

john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#   (use "git push" to publish your local commits)
#
nothing to commit, working directory clean

In the GUI client, the History pane now showed my check in too:

GitHub App - History

You may have noticed that the text output from the CLI indicated that “Your branch is ahead of ‘origin/master’ by 1 commit.” What that means is that my locally committed change has not been pushed to the central github repository yet, the “origin”, in the “master” branch of the code in which I am making changes. We can fix that easily enough with one command, entering my username and password when prompted:

john@Mac:~/py-junos-eznc/lib/jnpr/junos/facts$ git push origin master
Username for 'https://github.com': jgherbert
Password for 'https://[email protected]':
Counting objects: 13, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (7/7), 556 bytes | 0 bytes/s, done.
Total 7 (delta 4), reused 0 (delta 0)
To https://github.com/jgherbert/py-junos-eznc.git
   bfe0626..954b6c5  master -> master

And now we’re nice and clean:

john@Macintosh:~/py-junos-eznc/lib/jnpr/junos/facts$ git status
# On branch master
nothing to commit, working directory clean

Yeah! I just committed a change to my forked project! However, that does nothing for Jeremy, and I want him to incorporate my change into his project .

Pull Request

Back on the GitHub website, I browsed to my fork of the project and clicked on the “Compare & Review” (green) button:

GitHub Compare & Review

This generated a page showing the diffs between my code and Jeremy’s code, and the nature of the comparison was displayed at the top:

Submit Pull Request

The diffs shown further down the page were correct, so I clicked on the text saying “Click to create a pull request for this comparison”. A pull request is a way for me to ask Jeremy to consider merging my change into his project. It’s a neat system because it protects the main repository (owned by Jeremy), but allows me to submit potential updates for him to review and (hopefully) approve.

I then had a chance to write a comment about my proposed change. Effectively this begins a Conversation between Jeremy and I so that if discussion is required, it can be kept neatly along with the proposed change.

Pull Request Comment

At this point, Jeremy was sent a notification of the Pull Request and he was able to evaluate whether or not he wanted to merge this change to his code. In this case, thank goodness, it seems that I got this highly complex change correct and he merged my change back into his master project:

GitHub - Change Accepted!

Conclusions

That was kind of fun, and didn’t take very long to set up and get working. Most importantly, this showed me that GitHub is way less complex than it might seem at first and it turns out to be remarkably easy to contribute to a project this way.

I’m not entirely convinced that the native (GUI) app has much of a place in my nascent workflow; most of my changes were on the command line, which was a little disappointing.

It’s a little sad, perhaps, to be excited about checking in a typo correction, but as somebody who has not contributed to an open source project like this before, I can’t help myself (regardless of how utterly inane my contribution was)! Hopefully I can find way to be useful in the future, and use my newly-gained GitHub chops for the betterment of the world, or some equally lofty goal.

If you’ve been uncertain about GitHub, I really hope that this has given you some small insight into what an easy process it can be at a basic level, and perhaps by bringing together enough commands to follow through one process like this, you’ll take the plunge too in the near future!

Thanks again to Jeremy Schulman for throwing down the gauntlet – this was a really fun task!

4 Comments on GitHub N00b Makes Huge Edit to Juniper EZ Library

    • That’s great! I’m watching the project, so I was delighted when I saw a notification saying you had submitted an update.

      Thanks for coming back and letting me know. Hopefully we can get even more people on board and contributing.

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.