CS312 - Assignment two

Due: 2017-02-28 11:00a

Topics

Git

For those of you who don't know Git (and perhaps, for those of you who do), Git is a distributed version control system, and I think it is worth taking a step back to ask "why do I need a distributed version control system?". Unfortunately, most online references skip right to the mechanics and assume you are already using version control or know what you want it for.

Version control

So, first, what is version control? Version control is quite simply having a system in place that allows you to save checkpoints as you do work that you can return to. The simplest form is one that many of you have tried: save a copy of the file you are working on with a new name.

It should be fairly obvious why saving old versions is a good idea. It is fairly easy to break code, and it is handy to go back to earlier versions and start over. I think it can also make you more daring, more willing to make radical changes if you know that if it doesn't work you can jump right back to the working version. This can also keep your code cleaner, because there isn't a reason to just keep commenting out blocks of code on the theory you might need them back. Finally, it is good to have a history because you discover some new edge case that you weren't testing for and old copies of your application work, but new ones don't.

Dated file copies will work for a little while, but as projects grow and have more and more components, you will quickly lose track of things. This is where we step in with a dedicated version tracking tool that helps manages whole projects and gives us simple ways to quickly save versions and revisit them.

Collaboration

The second use for a version control system is to facilitate collaboration. The classic setup was a centralized project-level repository managed by a version control system. You would checkout the current state of the project into a local copy. You would make your changes, test them, and then push them back into the public repository.

There are a couple of issues with this model. First, you are not the only one coding. What if your fellow coder in the next cubical over happened to work on the same files you did and you created conflicting changes to the files? Second, you need to be able to connect to the repository to checkout code and check it back in, which may be problematic. Finally, you don't want to commit every little change you make into the master repository because it will screw up everyone else when you add half working code, so you lose most of the advantages of version control.

A partial solution to this was the introduction of branches. A branch is just a parallel version to the master code. This allows you to experiment, while leaving the master untouched until your new feature is ready to be merged back into the master.

A more complete solution to the problems was the introduction of distributed version control. The idea with distributed version control is that everyone working on a project has their own local copy of the repository. They can work where ever they want, and can pretend that they are the sole developer. When they are ready to share, they can push their changes out to someone else's repository or pull their changes in.

Everything is very fast, because everyone has a full copy of the history on their local machine, and you can make full use of the benefits of versioning without worrying what it will do to other people. There still tends to be a central repository to facilitate work by large groups (this is where GitHub comes in, for example), but there isn't anything particularly special about the shared repository other than the fact that everyone shares repository changes with the central repository rather than each other.

Git

That is a nutshell is why you might want to use a distributed version control system. I've left a number of details out, but hopefully that provides a little bit of context.

Now that you are prepped with the big picture, it is time to learn some of the mechanics of Git, and there are plenty of resources out there (including the builtin help in the man pages). However, your class/assignment will be a little more focused.

Assignment

Part 1: Install Git

You may already have it installed. Great! It is already installed on the Linux machines as well.

If not, you can get the latest version at https://git-scm.com/downloads.

Obviously, if you use a package manager (homebrew, apt, yum, etc), that would work as well.

Part 2: Read a quick primer

Starting work

There are three basic ways that you will start work on a repository.

  1. You could clone an existing repository: git clone some-repository.git

  2. You could create the repository using some higher level tool (for example, you might create a new project directly on GitHub)

  3. You could start with a directory and a dream: git init

In the first case, a new directory will be created where you are and the repository downloaded into it. In the second case, it depends on the tool. If it is an IDE like Eclipse or XCode, then it will all be pretty seamless. If you created the repository directly on GitHub, then you will need to also do git clone to make your local copy of the repository. In the third case, the current directory will be placed under version control (an optional argument can be used to create a new directory at the same time).

Adding changes to the repository

After you have made any kind of change (added a file, modified one). You can save those changes to the repository.

git commit -a

This will find all of your changes and save them. You will be prompted to add a message, which you should use to describe what has been changed. You can save a little time by using -m to add the message directly into the commit command.

While this will work, one of the reasons to use git over other systems is the level of control that it gives you. A common thread in working with version control is in telling a story with your commits, and we can do this by breaking the steps down a little further.

Committing changes to the repository is a two step process. Changes are first staged, and then they are stored. So, if we have three files with changes (fileA, fileB, fileC), but fileA and fileC have related changes, we can break this into two different commits.

~~~ sh git add file1A fileC git commit -m "Replaces the use of var with let" git add fileB git commit -m "Fixes some minor typos in fileB" ~~~

Note that we no longer use the -a because we only want to commit the staged changes.

Examining the status of the repository

There are three main commands for viewing history or looking at how the repository differs from the current working state of the directory.

git status

This will show you which files have been modified, which are new, and which have been deleted (along with a collection of other useful pieces of information about the current repository state).

git diff

This will show you what those changes are specifically. You can add in a filename to look at just what has changed about a particular file, and you can use references to earlier commits to compare to early versions.

git log

This will show you the history of commits you have made to this repository. You will notice that each commit is accompanied by a very long number, called the SHA-1 hash. This is a hash formed by the changes and should be unique to this particular commit. You can use this when referring to different commits. Frequently only the first few digits will be sufficient to uniquely identify which commit you meant.

Branching and merging

Branching is an important topic in version control. A common reason to branch is so that you can experiment with some new feature. This allows you to have a main branch which is stable, but also available for small bug changes and incremental development, and the feature branch where you can go crazy and rip everything apart. This is also useful if there are multiple developers working on different aspects of the project.

git branch add-flying-car

This creates a branch in the project called 'add-flying-car'. You can then work on this branch with

git checkout add-flying-car

Now, all of your work will be stored in this branch of the repository. If someone asks you to fix a bug in the project, you can easily switch back to the master branch with

git checkout master

Of course, this will replace the contents of your directory, so make sure that you have committed your changes before checking out a branch!

Once the feature is done, you can merge the changes back into the master branch with

git merge add-flying-car

Do this from the master branch. Hopefully this will be done without conflict and you will be done. However, there may be conflicting changes to files (especially if work was ongoing in both branches). In that case, git will mark up the problematic files, and you will need to go through and make choices about which changes to make, and then recommit. (Frequently the polite this to do is to merge in the other direction first – into the feature branch, and get any conflicts out of the way before merging to master).

Remote repositories

When working collaboratively, or just using a remote repository like GitHub, you will need to periodically sync your local repository up with the remote one.

git pull

This pulls changes from the remote repository and merges them into the current one. It is best to be fully committed before doing this, lest the changes pulled down overwrite uncommitted work. This also has the potential for conflict, so be wary.

git push

This pushes the state of the local repository out to the remote repository. When working collaboratively, you will want to make sure that you pull and fix any conflict before pushing.

Everything else

This is just a quick introduction to the basic commands. There are many options and commands not covered here.

Learn more in the Pro GIT book.

Part 3: Setup a GitHub account

You should start at GitHub Education. The benefit of registering through here is that you can get private repositories for free while you are a student. (If you already have a GitHub account, getting the private repositories would still be a good idea).

Part 4: Clone a repository

On GitHub, create a new repository. Call it CS312-HW2. Make it private, and don't initialize it with a README, .gitignore, or license.

Now find a nice spot in the file system and type this in on the command line.


git clone  https://github.com/Middlebury-CS312-s17/color-picker-example.git
mv color-picker-example CS312-HW2
cd CS312-HW2

Renaming the directory isn't necessarily, but it makes things cleaner.

This is the example code from the color picker example. We are making a copy of it.

Currently, this repository thinks that my repository on GitHub is where it comes from. We need to change its "origin" to your new repository.


git remote remove origin
git remote add origin https://github.com/XXXX/CS312-HW2.git
git push -u origin master

For the new origin, use the link provided when you created your new repository rather than https://github.com/XXXX/CS312-HW2.git.

This removes the link to my repository, adds in one to your own and uploads the files to GitHub.

Go back to GitHub and click on the Code tab of your repository and you should see all of the files. If you don't try again / ask for help.

Part 5: Clean up

Remove index.html and index2.html from the directory. Rename index3.html to index.html. Do a git status to see how these changes are reported. Use git add to stage the three files. Use git status again to see the difference when the files are staged.

Now commit. Make sure the message reflects the changes made.

Type git log and look at the output.

Part 6: Make a branch

We are going to make the page a little more useful, but we are going to do it in a branch.

Use the direction to make a branch called text-example. If you type git branch you should see a list of your branches with the current one indicated with an asterix. Use the directions above to switch to the new branch.

I would like you to edit index.html. Put in a paragraph or two of text. This can be anything you like (though I'd advise you to avoid being offensive since I will be looking at it).

At the bottom of the page, add a button labeled 'Show Color Picker'. When the button is clicked, add the color picker to the page, and change the label on the button to 'Hide Color Picker'. When the button is clicked again, remove the color picker. You can do this either by actually adding and removing the picker from the DOM, or using CSS to show and hide it.

When the color picker is visible, changing its color should change the color of the text.

As you work, use git to save your work when you hit milestones (added text, added button, got the picker showing and hiding, etc…). There should be a record of your work listed in your log.

Part 7: Edit the master

Oh dear, while you have been working on the branch, word has come down that the color picker is too ugly.

Switch back to the master and make the color picker prettier. Center the block over the sliders, make the sliders bigger. Anything you like. Just make some obvious improvements to the color picker aesthetics. Don't touch index.html to do it, however.

Commit your changes.

Part 8: Merge it all together

Switch back to your branch and merge the master into the branch. If it works, switch back to the master and merge the branch into the master.

If you want to see a slightly more graphical version of what you have wrought, try git log --graph. You should the changes made to both branches and the eventual merge at the top.

Part 9: Push it up to GitHub

Push the changes to your repository back up to your new GitHub repository with git push --all. The --all is to make sure that the new branch you created also gets pushed up to the repository.

Part 10: Turn in your work

Add me as a collaborator on your work. You can do this with the + icon at the top of the page when you are looking at your repository on GitHub.

Grading

Points Criteria
3 GitHub repository correctly set up
5 Git history with correct branches and merges
5 Changes to color picker
5 Changes to index.html