Skip to content

Working with Git

Einar Baumann edited this page Jan 28, 2016 · 1 revision

Git is a version control system. We use it to keep track of code changes in our project. Among other things, Git lets us revert to an older version if something goes wrong, and makes it easier for more than one person to work on the same codebase.

This article gives brief introductions to some of Git's most important features.

Useful Links

If you're like me, you like to read more than just excessively brief wiki-articles from time to time. That's why I'm giving you a list sites containing fun and useful information about Git in general, as well as some cheatsheets that should be very useful for beginners:

Installing Git

If you're like me, you like to install software before you use it. Luckily, installing Git is easy.

Ubuntu

As usual, us Linux people have it easier than most. To install Git, simply open up your terminal and execute

sudo apt-get install git

Windows and Mac OS X

If you're one of the unlucky few using Windows or Mac OS X, you'll have to head over to the official download page. After downloading it, simply install it like any other program.

GUI Clients

If you're like me, you like to work efficiently. Day-to-day gitting can of course be done using the command line, but GUI clients can simplify tasks like committing changes and resolving merge conflicts. The clients can't usually do everything for you, so from time to time you will have to open up a terminal.

SmartGit

SmartGit is a closed-source Git client. It's free for non-profit work (which we count as, I asked).

Setting up SmartGit to work with GitHub is very easy (just follow the wizard), and it supports, committing changes, merging, viewing diffs and trees, and Git-Flow.

Gitg

Gitg is a free, open-source git client. I have not used it myself, but it is highly recommended by the interwebz.

GitHub Desktop

GitHub Desktop is simple and clean, and in my oppinion too much so:I cannot recommend using it. If you've never used Git before, you never will if you just stick to GitHub Desktop. This can be very problematic if you ever run into a problem, or if you need to use a Git feature not supported by GitHub Desktop (which includes most features).

Important Day-to-day Commands

git status # Check the status of the repository
git add path/to/file # Stage a file
git commit # Commit your staged changes
git pull --rebase # Get upstream changes
git push # Upload your changes

Getting Started

If you're like me, you usually need to get started before you actually do something. In this section I will tell you what you need to do before you can actually start writing code.

Cloning a Repository

Cloning a repository, i.e. getting a local copy of it which you can work on, is done by executing

git clone url

Creating a Repository on GitHub

The easiest way to create a new repository, given that you want it hosted on GitHub, is by creating it there. Simply click the big green 'New repository' button and make up a name. After doing this, clone the repository.

Creating a Repository Manually

Creating a repository manually is useful if you're going to host it on a server where you have SSH access, or if you just want to host it on your own computer. To do this, execute

git init --bare name-of-my-project.git

then clone the repository to some other place. The clone is the folder you will actually be working in. If you created the repository on your own computer, replace the url with the local path when cloning.

Commiting Changes

If you're like me, you like commit to stuff, and in Git you have to commit to everything you do (unless you want to stash or revert them). In Git you have to "stage" your changes before you commit them.

Let's say that you wrote some stuff in file A.doc and coded some stuff in file B.cpp, both in the folder directory within your repository. You first have to stage your changes. If we want to commit all our changes together, we have two options in this case. The first is to just stage everything

git add --all

The second option is to stage the directory containing the modified files (which in this case is everything)

git add folder

After staging the files for commit, we have to actually commit them. There are two basic ways to commit our staged changes. The first is to simply run

git commit

which will open up some text editor and let us write brief description of the changes. The second option is to write the descrition in the command

git commit -m 'Wrote and coded some stuff'

Commiting files separately

Generally, if you've made changes that are not closely related to eachother, you want to commit them separately. We do this by first staging one set of files, commiting, then repeating for the other files. In our case, we can do

git add folder/A.doc
git commit -m 'Wrote some stuff'
git add folder/B.cpp
git commit -m 'Coded some stuff'

## Commit messages
**Writing good commit messages is important.** There are many oppinions on how a good commit message should look like, and googling the interwebz yields many results, for example [this](http://chris.beams.io/posts/git-commit/) one.

Generally, you want to write one _short_ line summarizing you're changes and, optionally, a more thorough description after a blank line, like this:

Added error handling in function C.

Added error handling in function C because we experienced crashes under some specific condition. This could potentiall break class D. This commit addresses bug report 5.

This is easier to do if you just go with the simple `git commit` and write the message in the editor.

# Reverting Changes
Sometimes you want to just throw out some or all of the stuff you've done and just start from the last commit. If you want to just revert a file or a folder, use the `checkout` command:
```bash
# Revert file.cpp to last commit
git checkout path/to/file.cpp

# Revert folder directory to last commit
git revert folder/* 

Stashing Changes

If you want to keep your changes and you haven't staged or commited them, and want to move them into a different branch or maybe pull in some changes, you can stash them and get them back later:

git stash
# Do stuff like switch to another branch or pull some changes
git stash pop

Pulling and Pushing (in that order)

Always pull before you push. You usually can't push before you pull if there are upstream changes, but do it anyway.

To pull, i.e. to get changes from the remote server, execute

git pull --rebase

This will pull down the changes from the server and replay your work over it. Doing a rebase is preferable over doing a simple git pull because it avoids many merge conflicts and thereby unnecessary merge commits.

To push your changes, i.e. to upload your changes to the remote server, execute

git push

Resolving Merge Conflicts

If several people are working on the same project, merge conflicts will occur eventually. Git will tell you if you have a conflict when you pull new changes; do a git status to check which files have conflict. You can either go into each file and fix the conflicts manually, or use a merge tool (which is built into most GUI clients). After resolving the conflicts, do a git commit.

Working With Branches

When working on a big codebase with others, you normally don't want to be working on the master branch. Working in you own branch lets you experiment with changes without being iterrupted by other people's crap every time you want to push something.

Creating Branches

If you want to start working on a new branch you have to create it and push it to the server:

git checkout -b your-branch-name
git push --set-upstream origin your-branch-name

Updating Branches

If you've been working in a branch for a while, people have probably commited some stuff to the main branch (or any other branch) that you want for some reason. To get these changes into your branch, rebase the branch into yours:

git checkout your-branch-name
git rebase -i master # or any other branch

Merging Branches

When you're done working on your branch, you have to somehow get your changes into the main branch (e.g. master). You can do this by either just merging your branch into the master branch, which will likely cause some issues; or you can rebase the master branch into your branch, and then merge your branch into the master branch. A good disussion on this is found here, but here I will only explain the second option (as it is the best one in my oppinion).

# Switch to your branch
git checkout your-branch-name

# Get the changes from master into your branch
git rebase -i master 

# Switch to the master branch and merge your changes into it
git checkout master
git merge your-branch-name

Submodules

Often we want to use code from some old project repository in a new repository. We could just copy that code into our repository, but that would make our code base bloated, and if the other project is updated it's difficult to update our copy. A better way to do this is by using submodules. In Git, a submodule is a Git repository within another Git repository. The content of the submodule is not pushed along with the rest of the code, and when you clone a repository containing submodules they will only be empty folders.

Adding a Submodule to your Repository

To add a new submodule to your repository, simply execute

git submodule add url_to_a_repository

This will download the most recent version of the the other repository to your repository and create a .gitmodules file which keeps track of all submodules used by your repository.

Working With Repositories Containing Submodules

Getting the Submodules

If you get a normal clone of a repository containing submodules, the submodules will initially only be empty folders. To get the contents of these submodules, execute

git submodule init
git submodule update

When you start working on a new project, you can instead execute

git clone --recursive url_to_repository

to the the repository and all submodules.

Updating the Submodules

To update all submodules, go to the submodule's parent folder (e.g. the root of the main repository) and execute

git submodule update --remote

If you just want update one submodule, enter the submodule folder and execute

git fetch
git merge

Git-Flow

In time, we will start using the Git-Flow workflow for FieldOpt development. When that time comes, I may write about that. But for now, take a look at this excellent description.