git is a modern version control system for managing the sharing and versioning of your source code. git is a "distributed" version control system, as opposed to classical systems such as CVS and Subversion which are based on a single central repository. While distributed version control is very powerful, this tutorial will teach you to use git in a "client-server" fashion that mimics the classical version control systems that you may already be used to.
This tutorial assumes that you are using Linux.
Tip
git has many, many more advanced features than are presented in this tutorial. If you'd like to learn about them, git has a comprehensive set of man pages (man 1 git or git --help <command>), as well as the online Git Community Book. Try these references first if you get unexpected output or error messages from git commands.
Log on to Gitlab, add an ssh key, and then find your group's repository under the Projects tab.
Click your repository's name, and at the top of the page there should be a string you can copy of the form git@gitlab.cs.washington.edu:cse557-15sp/YOUR_REPO.git, where YOUR_REPO is your group identifier.
Copy that string, and in a shell (such as Git Bash or Git Shell), run:
$ git clone copied_string
This will create a directory named YOUR_REPO in the current directory
We recommend renaming the local copy of the repository to something more descriptive, by running:
$ git clone copied_string descriptive_name
This will create a directory named descriptive_name in the current directory
If you are prompted to enter your password that means you haven't set up your ssh keys in gitlab properly. Do that now to avoid repeated password prompts as you push and pull things from gitlab.
Navigate to the skeleton code, click on 'Download zip' on the top right and unzip the downloaded folder
Copy the contents of the unzipped folder (not the folder itself, just what's in it) containing the skeleton code into the repository you just cloned. Commit and push the code by running the following commands:
$ git add --all
$ git commit -m "initial commit"
$ git push origin master
The commit and update process in git differs slightly from that of other version control systems that you may have used. To illustrate how it works, we'll make a minor change to one file and create a new file.
Copy the contents of pointBrush.h and paste into a new file called lineBrush.h. Replace all occurrences of 'point' with 'line'. In impressionistDoc.cpp, add lineBrush.h to the brush includes. (search for pointBrush.h if you're having trouble finding this)
Now run the git status command and observe its output:
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: impressionistDoc.cpp Untracked files: (use "git add <file>..." to include in what will be committed) lineBrush.h no changes added to commit (use "git add" and/or "git commit -a")
This output shows two things: first, you must explicitly add new ("untracked") files to the repository before they can be committed (as is true in other version control systems), and second, you must explicitly stage your changes before they will be committed (unlike subversion, which will automatically commit all of your changes if you just run svn commit). To further illustrate this, run the git commit command:
$ git commit -m "Adding the line brush header file."
This command will be a no-op: you should see the same output as from the git status command, ending in the same message: 'no changes added to commit (use "git add" and/or "git commit -a")'. To add your changes to the commit set, you must use the git add command on the changed files (whether they are new files or files already in the repository!):
$ git add impressionistDoc.cpp $ git add lineBrush.h $ 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: impressionistDoc.cpp new file: lineBrush.h
You can see that the change to the impressionistDoc.cpp file and the addition of lineBrush.h have now been staged for the commit. To commit all of the changes that you have staged, run git commit:
$ git commit -m "Adding the line brush header file." [master 41a5c0d] Adding the line brush header file. 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 lineBrush.h
Details
The -m argument to git commit is used to provide a commit message; if you forget to use it, then git will open a text editor for you to enter a commit message.
To make git behave more like subversion and automatically commit all of the changes you have made to files already in the repository (automatically commit all unstaged changes), use the -a flag with git commit. You may find, however, that the process of staging / unstaging changes is one of the most useful features of git: it allows you to make lots of changes to lots of files, but only commit the changes you want while leaving other files with in-progress changes uncommitted.
If you get a message like "file.c: needs merge" when you try to commit, then you have a conflict from a previous git pull that has not been resolved. See the Updating your local repository section below for more information about resolving conflicts.
However, at this point you have committed some changes, but your commit is not yet visible to the other users of the repository. git separates the notion of committing changes from the notion of "pushing" your update to the central repository. This can be useful for an individual developer that wants to make many changes to the code in many small logical commits before pushing all of them to the central repository, but for your CSE 557 projects you will probably just want to push after every commit.
To push your commits to the central repository, simply run git push:
$ git push Counting objects: 4, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (4/4), 312 bytes | 0 bytes/s, done. Total 4 (delta 0), reused 0 (delta 0) To git@gitlab.cs.washington.edu:cse557-15sp-impressionist/YOUR_REPO.git eb27358..c3615e1 master -> master
Note
If your push fails, it may be because you need to run a git pull to update your repository first (and potentially resolve conflicts) before pushing your new commit. See Updating your local repository below.
Note
If you get a warning that push.default is not set, you can make that message go away by setting it to simple using the git config command given in the warning message.
Details
If you ever run the git status command and see the output "Your branch is ahead of 'origin/master' by N commits", then this means that you have local commits that have not been pushed to the repository yet.
Reminder
Remember to push your commits! If you are not used to using git, then this may be the hardest thing to get used to. Try not to forget to do this, or your group members will wonder why it seems like you're not doing any work.
To update your local copy of the repository with commits that other members of your group have made, simply use the git pull command. It will either show:
$ git pull Already up-to-date.
or something like:
$ git pull ... impressionistDoc.cpp | 1 + lineBrush.h | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 lineBrush.h
Note
git will not allow you to pull updates into your repository while you have unstaged changes. Therefore, you must stage (git add) and commit all of your changes before pulling. If you have changes that you don't want to make visible to your group yet (because they cause the build to break, for instance) but you still want to update your local repository, you can just commit your changes, do not push them yet, and pull the updates. Then, when your changes are ready, you can commit again and then push to the central repository.
As with any version control system, pulling updates from the central repository may cause conflicts with changes that you have committed locally. Pay attention to the output from your pull command for instructions to resolve conflicts; generally, resolving a conflict entails opening up the conflicted file(s) in your editor, finding the conflicts (surrounded by the text markers <<<<<<<, =======, and >>>>>>>), fixing the conflicting code, staging the changes (git add) and committing and pushing again. For more information about resolving conflicts, the github user manual has a useful webpage.
If you don't feel comfortable working on the command line, you can use a git gui client. The lab machines have Git Gui installed, but feel free to use any gui you feel comfortable with on your own machine. Here is a list of third party guis if you don't like Git Gui.
Git Gui requires that the repository be populated with something before cloning it. If you don't already have the skeleton code in your repository, complete the Cloning the repository and Committing the skeleton code steps above.
If you already have a local repository (if you've run the command git clone)
If you do not have a copy of the repository
Note
Replace the red underlined text above with your group's repository.
Note
The target directory must not exist beforehand. In the image above, the impressionist directory does not exist on the Z: drive - the cloning process will create it and place the contents of the source into the target
Copy the contents of pointBrush.h and paste into a new file called lineBrush.h. Replace all occurrences of 'point' with 'line'. In impressionistDoc.cpp, add lineBrush.h to the brush includes. (search for pointBrush.h if you're having trouble finding this)
Hit the 'Rescan' button to see your changes in the gui
We now want to stage the files we added/changed, then commit them. Hit the 'Stage Changed' button. You should see the files move from the 'Unstaged Changes' box on the top left to the 'Staged Changes' box on the lower left. Add a commit message, then hit the 'Commit' button.
Finally, we want to push this commit to the origin. Hit the 'Push' button. You should now be able to view your changes on GitLab, and your partner is set to pull the changes.
Unfortunately, Git Gui does not support the git pull command, so we have to first do a git fetch followed by a git merge
.You can visualize your branch history by selecting 'Visualize master's History' or 'Visualize All Branch History' under the Repository menu.
If you find any bugs in this tutorial, please e-mail them to the CSE 557 staff. If you have any problems while using git that are not covered in this tutorial, try the man pages (man 1 git and git --help <command>) and the Git Community Book, and then contact the TAs. If you find any useful features of git that aren't mentioned here, post them to the class discussion board.
Author: Peter Hornyack (pjh@cs)
Edited by: Sunjay Cauligi (sunjayc@cs), Nat Mote (nmote@cs), Hal Perkins (perkins@cs), Sonja Khan (sonjak3@cs)
Adapted from the CSE 401 git tutorial