Working with Git and Local Project Branches

I've been studying up on Git and how to use it, here.

My goal was to rationalise a somewhat messy local disk folder structure of multiple personal Sparkcore projects, whilst benefitting from Git branches for both personal versioning control and upstream updates -- all in a clean, uncluttered manner, on GitHub. (What a mouthful!)

Starting With a Clean Slate (almost -- but not cutting ties)

What I now have is 'my own' GitHub repository forked from spark/core-firmware, wherein resides only the master branch and one branch for each of my own Sparkcore projects. Currently, it looks like this ...

My Rationale or, "Why I did this"

I wanted my own GitHub repository, to contain a record of my local Sparkcore projects. This needed to be a clean affair, so I didn't want to have copies of all the other branches present on the official Spark core-firmware repository, at the time I forked my own copy.

I will first explain how I use the final result and later how I set it up this way in the first place.

Working on Individual Projects

After cloning a local working copy of my forked repository using git clone https://github.com/gruvin/core-firmware.git, I can now work on each of two currently published projects using the git checkout command. It goes something like this ...

$ cd ~/sparkcore-forked/core-firmware
$ git branch
  gruvin/chibi-port
  gruvin/dryer-timer
* master

This tells me I am in the master branch of core-firmware.

NOTE: I should never change any files in here, because I want my master branch to always echo the official Spark core-firmware code, without any chances by me.

Now, I have two existing projects, each in their own branch. Let's do some work on the project I have named gruvin/chibi-port ...

$ git checkout gruvin/chibi-port 
Switched to branch 'gruvin/chibi-port'
$ vi src/application.cpp

I chose the naming convention, 'gruvin/project-name' only so that should I some day write a new Sparkcore library and offer it as a pull request, I am less likely to collide with some existing branch name, back in the official Spark core-firmware repository. If you don't like this, you can simply omit the 'whatever/' prefix.

After reaching each little milestone win with my code, I want to record my progress in a local commit. I'll skip the staging process by using the -a argument to commit, because I'm lazy ...

$ git commit -a -m 'Finally! The radio is sending and receiving pings! Yay \o/'

Later, it comes to pass that my gorgeous wife informs me how it would nice if our IoT-connected clothes dryer had some subtle new feature. So, let's change to that project and get it done ...

$ git checkout gruvin/dryer-timer 
Switched to branch 'gruvin/dryer-timer'
$ vi src/application.cpp

After testing and attaining that state of happiness only a hacker/maker can know, I commit my changes, again just locally ...

$ git commit -a -m 'Reduced cool down time from 10 minutes to 5, so clothes come out still a little warm in winter'

Publishing Work to GitHub

When I'm ready to publish my work to GitHub (aka update my off-site backup) I would execute something like ...

$ git push origin gruvin/dryer-timer

Bringing in Updates from the Official Spark core-firmware

After I forked my own core-firmware, I added a reference to the official Spark core-firmware repository, so that I can pull in future, external (to me) updates ...

$ get remote add upstream https://github.com/spark/core-firmware.git

I can now fetch updates from the official Spark core-firmware repository as follows. Note that this step sucks down the updates, but does not actually apply them to any of my forked branches, yet ...

$ git fetch upstream

Now I can apply the updates to one or more of my branches. Let's sync up my master branch, first ...

$ git checkout master
Switched to branch 'master'
$ git merge upstream/master

I can use the same sort of command to update my other two projects or, having already got my master branch up to date, I can merge that to my other branches, by first checking out the target branch and then using git merge origin/master.

Grabbing a Light-weight Copy of Just One Project Branch

If I wanted to clone a copy of just my dryer-timer project's core-firmware folder, skipping all but the most recent history in order to keep the cloned copy as small as possible, I can do something like this ...

$ git clone -b gruvin/dryer-timer --single-branch --depth 1 https://github.com/gruvin/core-firmware.git core-dryertimer

... which will result in a folder named core-dryertimer/, containing only the gruvin/dryer-timer project and only the last commit's worth of history.

How to Delete Unwanted Branches in Your forked Repository
... or how I got my forked repository cleaned out to have only master and my own project branches.

Branches reside in two places -- your local working copy and on the GitHub server. You have to delete each copy, separately.

  • To (forcibly) delete a local working copy branch, the command is git branch -D unwanted-branch.

  • To delete the server repository copy of that same branch, the command is git push origin --delete unwanted-branch

When I first forked spark/core-firmware, there were quite a few branches. It would have been tedious to delete them all, one at a time -- twice, once locally and once on the server. BE VERY CAREFUL with this. But here's how I removed all but the master branch, in just two steps ...

First locally ...

$ git branch -a | grep -v "master" | cut -f3,4 -d\/ | xargs git branch -D

Then on the GitHub server ...

$ git branch -a | grep -v "master" |  cut -f3,4 -d\/ | xargs git push origin --delete

The cut -f3,4 -d\/ section is there to reduce the full branch names given by branch -a down to the names required for the delete command. So, remotes/origin/compile_server2 becomes just compile_server2 and remotes/origin/feature/foo becomes just feature/foo

Summary

We have looked at a method to locally organising Spark projects under versioning control using Git. We've seen how to publish our work to our own GitHub repository, which more cleanly contains only our own projects plus the master branch. We saw how to update our forked repository with changes made to the upstream repository, from whence we forked.


"Eat your heart out Subversion. I'm never going back! :stuck_out_tongue:" -- Gruvin 2014-04-22.

9 Likes

Thanks a lot @gruvin, I’ve been trying myself to come up with an easy but organized workflow to manage git reading Atlassian Workflows and definitely will be using your suggestions.

Another good read for understanding git is A successful Git branching model. It really helped me get my head wrapped aroung git.

2 Likes

@gruvin Thanks for the writeup gruvin. Can you tell me what you meant by “official spark firmware”? I got lost where you mentioned that you would like to pull the official spark firmware code to your own repo, you would only do that if you are working on the official firmware. Why would the personal projects depend on the official spark firmware?

@krazineurons, I think @gruvin meant the “infrastructure” firmware like core-common-lib, core-communication-lib and core-firmware. These repos supply a lot of things your own project will use unless you are building a bare mettal project.

E.g. all the wiring basic functions are put together in the core-firmware, you’ll find.

These repos you can find in the “Open Source” section.