Skip to content
Ryan Moore edited this page Jun 14, 2016 · 1 revision

Spectra Logic's Github Developer Workflow

For all Git repositories hosted on Github, Spectra uses the following workflow to develop and contribute code. The following provides an introduction to the workflow and the exact steps to take to contribute changes to the repositories.

Overview

The following diagram gives an illustrative overview as to the steps required to get a repository cloned onto your local machine and how to get changes merged back into the main SpectraLogic repository.

Github Workflow

1) Fork The Repository

It's important to fork the repository first before doing any work with the SDK. While you can work in a branch off of the main repository, this is discouraged since you can create your own branches in the fork and push to your fork without any worry of those pushes showing up in the SpectraLogic repository. Github has published some documentation on creating your own fork.

2) Clone your Fork

Next you'll want to clone a copy of your fork, not the Spectra Logic repository. This is important to help prevent your local copy from becoming out of sync with your fork. To clone your fork, from the command line type: git clone https://github.com/<Your Username>/<repoName>.git

As an example, if I were to clone my copy of the ds3_java_sdk I would type: git clone http://github.com/rpmoore/ds3_java_sdk.git

To verify that you've cloned your fork type git remote -v. You should see 2 entries both named origin. Here is an example of what you should see:

$ git remote -v
origin	https://github.com/rpmoore/ds3_java_sdk.git (fetch)
origin	https://github.com/rpmoore/ds3_java_sdk.git (push)

A remote is just a remote repository that our local git knows about. origin is the default remote when cloning a repository and is used by default in many git tools. It's not required that you have a remote named origin, but it is a convention that will work with most git tools.

We will then add a new remote called upstream that points to the SpectraLogic repository. To add a new remote type: git remote add upstream https://github.com/SpectraLogic/<repoName>.git

An example of doing this:

$ git remote add upstream https://github.com/SpectraLogic/ds3_java_sdk.git
$ git remote -v
origin	https://github.com/rpmoore/ds3_java_sdk.git (fetch)
origin	https://github.com/rpmoore/ds3_java_sdk.git (push)
upstream	https://github.com/SpectraLogic/ds3_java_sdk.git (fetch)
upstream	https://github.com/SpectraLogic/ds3_java_sdk.git (push)

Now we can pull from upstream and push to origin.

NOTE: You can always rename your remote by using the git command git remote rename <old> <new>

3) Push Commits

Now that your local repository is ready for work, you can go ahead and make commits to your local copy of the repository. It's important to note that with Git when you make a commit it does not show up in any other repositories until it is pushed. This is due to how Git is architected. Each repository contains the whole history of the repository and is its own independent repository. To move changes from your local repo to your fork use the git push command.

Let's say I make a change to the README.md file updating some documentation in the ds3_java_sdk repo. In my local copy of the repository I'll make my change and then add it to be committed(in Git this is called staging):

$ git add README.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified:   README.md

This means that I can now commit the change.

$ git commit -m "Updated README.md with some changes to formatting."
[master 5764928] Updated README.md with some changes to formatting.
 1 file changed, 1 insertion(+), 1 deletion(-)

My change has now been committed to my local repo, and now it needs to be pushed to my fork.

NOTE: You will only ever push to your fork and pull from upstream. If you do not do this your repos will get out of sync and you will have to do some major merging or blow away your fork and redo any changes to the fork.

To push a change use git push origin master. This will push your changes to the remote repository origin and will push the branch master. More on branches later.

Pushing will take any commits you have in your local repo and copy or 'push' them to your fork. This assumes that origin is pointing to your fork(which it should!!!)

Here is an example of pushing the commit from above to my fork:

$ git push origin master
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 345 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://github.com/rpmoore/ds3_java_sdk.git
   cc2f3ba..5764928  master -> master

Now with our commit on our fork we can create a pull request.

4) Pull Request

Pull requests are the mechanism by which changes made to a fork are merged into the SpectraLogic repository. All changes must come from a pull request. Github has a great writeup on creating pull requests but the gist is that, when code changes are ready to be merged with the SpectraLogic repo, you create a pull request with the changes, and the changes will be code reviewed and any associated unit tests will be ran. If a code review does not happen, or the unit tests do not pass, the pull request will not be merged into the SpectraLogic repository. Github will actually disallow you from merging if the unit tests fail.

Once the unit tests have passed and a code review has been conducted by another member of the team, the team member doing the review will merge the code into the SpectraLogic repository.

If it is determined during the code review that there needs to be any changes, or the unit tests fail, you can make updates to your pull request by pushing new commits to your fork to the same branch. The pull request will be updated, and the unit tests will re-run. If you are working on other items while waiting for a pull request to be merged, this is where you will want to create a branch. Again more on branches later.

Now that your code is merged into the main repository there is one last thing left to do. It's very important not to skip this step or your repositories will become out of sync.

5) Pull from Upstream

Now that your changes have been merged into SpectraLogic's repository (or upstream) it's time to pull those changes to make sure that your local copy and fork have the latest commits.

When a pull request you submit is merged a new commit is created. You need to make sure that this commit is in both your local copy and your fork. To pull the changes into your local repo use:

$ git pull -r upstream master
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/SpectraLogic/ds3_java_sdk
 * branch            master     -> FETCH_HEAD
   cc2f3ba..724ffb4  master     -> upstream/master
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 724ffb454e4739a6b8c822a271fefad8df067ecd.

You can use git log to verify you have the latest commits and merge from upstream. You now need to push to your fork to finish the last step. Like before when you pushed your commits to the fork you will again do git push origin master.

A note on -r A quick note on the -r option used when doing a git pull. -r means to perform the pull request as a rebase. Rebasing will take all your local changes and apply them after the commits from the remote are pushed onto your history. Atlassian has a great tutorial on what exactly a rebase means.

Unless you have to, you should always pull changes from upstream with the -r option. If you do this right after your pull request is merged you should not have any problems. The only time a rebase will become a problem is if you have not rebased in a while and there are several changes in your repo and in the SpectraLogic repo with overlapping changes(changes to the same line). When starting any new work in your local repo you should issue git pull -r upstream master to make sure you have the latest changes to help avoid any merge conflicts.

Branching

Now the section on branching. Branching allows you to have several streams of development in the same repository, at the same time. You can think of them as light weight forks. And just like forks you want only one or two branches active at a time.

The only time branches should be used is if you are waiting for a pull request to be merged and you are wanting to push your changes to your fork. To create a branch you can issue git branch <newBranchName>. This will create the branch starting from your current commit. It's important that you checkout that newly created branch. To see what branch you are on use:

$ git branch
* master

If you have not created any branches you should only see master, and the asterisk next to it. The asterisk denotes which branch is currently checked out.

When you create a new branch, say readme_updates, you'll see the following:

$ git branch readme_updates
$ git branch
* master
  readme_updates

You'll notice that the branch now appear, but it is not the currently checked out branch. To checkout readme_updates issue:

$ git checkout readme_updates
Switched to branch 'readme_updates'
$ git branch
  master
* readme_updates

Now readme_updates is the currently checked out branch. Any commits made now will be made to the readme_updates branch.

What If I already made commits to master but don't want them in master If you have already make commits to the master branch you can branch and then revert the master branch to remove your new commits.

Say you've made one commit to the master branch but you want that commit in a new branch. Use git reset --hard HEAD~1 after you create the branch that contains the new commit. This will reset your HEAD or the current latest commit, to one commit back. Here is an example of committing a change that should have been made to a different branch than master and then moving that commit to a branch:

$ git commit -m "Adding intellij instructions to the README.md"
[master dc85957] Adding intellij instructions to the README.md
 1 file changed, 3 insertions(+), 1 deletion(-)
$ git branch readme_updates
$ 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
$ git reset --hard HEAD~1
HEAD is now at 724ffb4 Merge pull request #104 from rpmoore/master
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
$ git checkout readme_updates
Switched to branch 'readme_updates'

Now that you have your branch you need to push your new branch to your fork. Just like pushing your commits from step 3 you'll use git push but with one major difference. Instead of git push origin master you'll issue git push origin <branchName> instead. An example of this:

$ git push origin readme_updates
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 385 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://github.com/rpmoore/ds3_java_sdk.git
 * [new branch]      readme_updates -> readme_updates

You'll notice that it says a new branch was created. If you look at your fork on github you'll now see a new branch. With this new branch you can submit a new pull request from that branch and the changes from other branches will not be seen in this pull request.

It's important that once your changes are merged from your branch that your local copy is updated to reflect the new pull request's merge:

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git pull -r upstream master
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/SpectraLogic/ds3_java_sdk
 * branch            master     -> FETCH_HEAD
   724ffb4..b6ecd83  master     -> upstream/master
First, rewinding head to replay your work on top of it...
Fast-forwarded master to b6ecd837b84a18d10bffdbbbbaf8aba7d3635daa.

If you look at git log you should see the new commits from your branch at the top.

Summary

  1. Fork repo
  2. Clone fork git clone https://github.com/<YourUserName>/<repoName>.git and setup upstream remote git remote add upstream https://github.com/SpectraLogic/<repoName>.git
  3. Commit changes git add <modifiedFile> git commit -m "<commit message>" and push changes git push origin master
  4. Create pull request for code review
  5. Pull changes to local repo git pull -r upstream master and push to fork git push origin master
Clone this wiki locally