Learning Git - northern-bites/nbites GitHub Wiki

Learning Git

Git is a distributed revision control and software-management package. So that’s a lot of words. Git is basically a piece of software that allows you to manage changes to code, papers, or other documents. We use Git to manage our code, but there are also people that use Git to write papers more efficiently among other things. What Git allows you to do is make a bunch of changes to some code to experiment with it, and then “commit” those changes if it works, or revert back to the previous working version if it didn’t. It’s like going back in time. But the great thing is that you don’t have to manually dig through and change everything back to the way it was from your memory. We let Git remember what we did for us because we are programmers and programmers are lazy. Another cool thing about Git is that once you commit some changes, you can decide much later that they don’t work after all and revert back to before you made those changes too. And it’s uber fast.

So we’ve covered most of the terms in that first sentence. Software-management package: Git is just a piece of software for managing code and documents; revision control: Git lets you apply and cut out your changes at will; but what about distributed? What does that mean? Git is only one of many version-control systems. The team used to use a very popular system called Subversion or SVN for short. It is similar to Git in a lot of ways, but lacks many of Git’s most powerful features. First off SVN is centralized rather than distributed. This means that the “repository” (everything that SVN is told to keep track of) is centralized somewhere on a server. For users to access the code and make changes, the user has to connect to the server and check out the most recent version then connect again when they are done. With a distributed system, every user has a copy of the full repository and even has the option of keeping copies of what other users are changing. This allows for a much more flexible development environment. In addition to this, Git provides better “branching” capabilities. With one branch, a developer can be working on one part of the code, say Vision, while simultaneously working on Motion in another branch. This is especially useful when development areas overlap and you want to keep your changes for each area separate. Git has fantastic merging algorithms to handle conflicting changes so there’s no need to worry about that.

New to the Northern Bites? Once you think you have all of this stuff figured out, you can start going through our tutorials here.

Key Terms

Repository

A repository is where all of the code is located and kept. This is also the base directory. Our repository is called nbites. A repository can be “local” (on your own machine) or “remote” (on a server like Github).

Commit

A commit is a group of changes (typically with a message) that serve a common function. For example, I might add debug print lines to a file and commit that with a message

adds debug prints
And I may add another commit that adds a new function, and another that adds comments to a file. It is generally a good thing to commit a small number of things often, rather than large number of things infrequently.

Branch

A branch is a collection of commits usually with a common purpose. For example, I might create a branch called vis-better-ball and commit a bunch of little things with the greater purpose of seeing the ball better.

Staged vs Unstaged vs Untracked

Changes that you make in Git can be either untracked, unstaged, or staged. Suppose I have an empty Git repository and I create a new Java file called Hello World.java that has just a main method that does nothing yet. This file is currently untracked because I haven’t told the repository to keep track of it yet. I can do so with a simple command that we will get to in the next section, but for now suppose I tell the repository to track it and I commit the state of the file.

Now I realize that I haven’t actually printed “Hello World” in my program yet, so I add that into the file and test it and it works. Note I still haven’t committed anything to the repository and I can still test the full functionality of my program. But of course I want to commit these changes. Currently, the file is unstaged; it is modified, but I haven’t told the repository that I intend to commit it yet. I can run a command to put the file in the “staged” area which we will get to in the next section. Now when I run the command to commit, only the staged files will get committed.

Something else of note to point out now is when I compiled and tested my Java program, a Hello World.class file was generated by the compiler. This file is untracked because it is new to the repository and I haven’t told Git to track it yet. But I don’t really want to track the .class files and I don’t want to see them all when I check the status of the repository. Git has a solution to this problem as well. There is a hidden file called .gitignore that is in every repository. You can add all the files (or even kinds of files using regular expressions like *.class) that you want Git to ignore in this repository. Handy huh?

Checkout

“To checkout” is an action that can mean a couple different things in Git. The first and most common is to checkout a branch. This allows you to move from branch to branch as you please. Note you can only change branches if you have no outstanding changes, so you either have to commit the changes or use the stash command to store them away and then the stash pop command to bring them back. The other meaning of “checkout” relates to unstaged changes; You can checkout unstaged changes to revert back to the state they were in before you changed them.

Master and Develop

Every version of the repository, remote or local, has a master and a develop branch. Master, for our team, is the branch used for the most stable software, and only gets updated when new code has been thoroughly tested and we are sure that the new version will be just as stable as the previous one. Develop is our most stable working branch; you can think of it as a more updated version of master that we do not yet consider stable enough. You can read more about how we manage these branches here.

In your local copy of the repository, you should try to keep as up to date with the remote versions of master and develop as they are updated. Because develop is a working branch, it is updated fairly often as changes are made. So before you make a new branch off of develop, make sure you remote update and pull any changes that may have been merged in recently.

Structure of Repositories

As of summer 2016, we are using a version control style called Git Flow. Make sure you read about our coding style thoroughly and ask questions about anything confusing before starting to write and push code.

Learn by Example

Now we are going to learn the every day commands through an example. There are plenty of places you can find a list of the commands and their uses (see below), but hopefully this example will provide a different insight.

So let’s suppose we want to work on a new kick for our robots. First CD into the nbites directory(repository). The first thing we want to do is make sure we have the latest master. To do this we must update our remotes (of which the northern-bites/nbites repository is one if you followed the instructions in Configuring Git) by running the command

$> git remote update

This will update all of the branches on all of your remotes. Next you need to merge the remote develop into your local copy of develop. To do this, you run
$> git checkout develop
$> git pull origin develop

Origin is the northern bites repository, where you are fetching and merging the new version of the branch. Since we no longer for (again, as of summer 2016), you don’t need to worry about pulling from the right remote. You should only have one.

Now that you’re all merged there you need to create a new branch to work on your new kick. So run the command

$> git checkout -b be-new-kick

which will create a new branch called be-new-kick and check it out for you all in one step. New kicks are generally made in the SweetMoves file in behaviors, which is why you would probably use be- instead of mo-, unless you’re working on a kick engine. You should probably also name your branch something a little more specific, but let’s just use this one for simplicity’s sake.

Now you can change things all you want. There are many parts to a kick so perhaps you will commit each part of the kick (the windup, the kick, the follow-through, …). So lets say you have the windup tested and ready to commit. The files are probably unstaged, so you run

$> git add [name-of-the-file]

for each file you want to commit. Then once that is all done, you run
$> git commit -m "adds windup for new kick"

This will commit all the staged files with the message in quotes. You would do this until the kick is as close to perfect as possible.

At this point you want to merge any changes that could have been made in develop into your branch before pushing. As you’ve read before, make sure your version of develop is up to date.
So you run the following commands:

$> git checkout develop
$> git remote update

And pull any changes with

$> git pull origin develop

Then to merge all of the changes into your kick branch, you want to check out your branch again and merge develop into it.

$> git checkout be-new-kick
$> git merge develop

There shouldn’t be any merge conflicts, but if there are, you should fix them before continuing. Fixing merge conflicts is outside the scope of this guide but if you encounter them, you should feel free to ask a veteran about how to fix them, but I digress…

Finally you need to push your updated branch to the remote repository so that the team leaders can put it into develop. To do this run

$> git push origin be-new-kick

Then you go to your Github page and click on the “Pull Request” to create a pull request so that the leaders will know about your changes.

Advanced Commands

This section provides some detail on some more advanced commands, ones you won’t run everyday. If you find a cool command or option, feel free to add it!

Deleting Branches (local and remote)

To delete a local branch, be in a different branch and type $> git branch -d [branch-name] and to delete a remote branch, type $> git push [repository] :[branch-name] which actually pushes nothing into that remote branch (which has the same effect as deleting it on Github. So handy!

Rebase

NOTE: This and the following section (Resetting your master) are not really relevant anymore; please ignore it until the team has edited it. The stuff after it is still useful, though.

CAUTION! Rebasing can cause more harm than good. Make sure you know what you are doing.

You should attempt to keep your branches up to date with the nbites/master. The easiest way to do this is to have a github remote called nbites, and regularly run these commands:

$> git remote update
$> git checkout master
$> git rebase nbites/master

Rebasing will take all of the commits you have made in your master branch and put them on top of all the ones in the nbites/master (i.e. it’s as if you made all the commits after all of the ones in nbites/master). This is dangerous if your commits generate conflicts with the ones in the nbites/master. Rebasing will not generate merge conflicts since your changes will effectively come after the ones in the nbites/master. If you are worried about conflicts, you can always merge instead, which will create it’s own commit with any conflict resolutions (possibly 0). If merge conflicts occur, you should talk to whoever wrote the code that is causing conflicts before you try to resolve them. That way, you can ensure that the resulting code will still function as intended. You should rebase your working branches from your own master now and again as well.

Resetting Your Master

Your master branch should always be the same as the nbites master, unless you have a pull request open. If, for some reason, you have extra commits in your master that you don’t want to put in a pull request, there is a way to reset your master back to the nbites master. Assuming you have a remote repo called nbites, run these commands:

$> git remote update
$> git checkout master
$> git reset --hard nbites/master
$> git push -f

Notice that the -f option is needed when pushing to your remote if you have pushed extraneous commits to it. Be careful when resetting your master! Unless you have them saved in some other branch, the commits that are deleted are gone forever (which is a very long time).

Commit Parts of Files

Sometimes you realize you want to commit only some of the changes you’ve made to a file. Good! because Git can work with lines of code instead of a whole file. Use

$> git add -p file

to “patch” in part of a file interactively!

Commit All Files

If you’ve edited lots of files, it can be a pain to add each one. There’s a few options for you:

$> git add file1 file2 ... will add all the files that you chain together in one command

$> git commit -a will commit every file you’ve changed, moved, deleted, or created.

$> git commit -u will commit every file you’ve changed, moved, or deleted, but won’t add any untracked files to the commit.

External Resources

This page has some links to guides that will help you learn how to use git.

  • Git homepage is a great place to explore. There’s lots of useful videos and information that you should peruse.
  • ProGit is a free online book on “Effective Git Use.”
  • Github training is a good site for new users and experienced users alike.
  • Git Class is a great class tutorial which walks you through a simulated terminal and integrates with your github account.
  • Git Immersion is a long walkthough. It guides you through several labs, teaching you commands as you go. It focuses on a lot of commands that aren’t super useful, and leaves off some of the important ones, so it isn’t a good reference once you have a sense of how to use git.
  • Git Magic is an overview of git.
  • Git for the Lazy is a very short reference guide.

Git Tweaks

You should also check out the bottom of the Configuring Git page for some very useful personalizations. They will make your life much easier, trust me.

⚠️ **GitHub.com Fallback** ⚠️