Section 2 - Using Git to Track a Project
G2.1 The Project Folder
By using an IDE, we are often shielded from the details of our project. One of these details is the knowledge about a project's location within our computer's file system. Where is it? To answer that question, read the section below that pertains to your operating system and IDE.
Location of Project Folder On Windows/VC++
Here is a project I'm calling Assignment_1, as viewed from our IDE:

We can't quite tell where this lives on our system, so a little investigation is in order. On my computer, here is where I find the project's payload:

In other words, if one uses the default settings when installing Visual Studio, your project Assignment_1 will be in the following path:
C:\Users\<YOU>\Documents\Visual Studio 2008\Projects\Assignment_1\Assignment_1
Notice that there are two folders with the name Assignment_1. It is inside the second, or inner, Assignment_1 folder that our project files actually live.
Find the location of any one of your VC++ projects and, make a note of the folder location, because you'll need it for the next step. It should be similar to mine, above.
Location of Project Folder On Mac/Eclipse
Here is a project I'm calling Assignment_13, as viewed from our IDE:

We can't quite tell where this lives on our system, so we search on our desktop. On my computer, here is where I find the project's payload:

In other words, if one uses the default settings when installing Eclipse, your project Assignment_13 source files will be in the following path:
<YOU>/Documents/"java workspace"/Assignment_13/src
Find the location of any one of your Eclipse projects and, make a note of the folder location, because you'll need it for the next step. It should be similar to mine, above.
G2.2 Configuring Git
You will use the git config command now to create an identity that will be used to distinguish your changes from someone else's (like another team member). The following two commands (with your info used in place of Dr. Sheldon Cooper's) will accomplish this. Ignore the lines starting "michael..." . These are just part of the Bash prompt on Windows. The command is typed after the $.
michael@MJL-3A-VISTA64 ~ $ git config --global user.name "sheldon cooper" michael@MJL-3A-VISTA64 ~ $ git config --global user.email coopsheldonfox@ucla.edu michael@MJL-3A-VISTA64 ~ $
There are other configuration options that we can ignore for now. These are the two important ones.
G2.3 The Repository
Navigating to the Project Folder
Using the command cd to change directory, we can navigate to our project folder. Start your Git console (using Bash on windows or Terminal on a Mac), and execute the command cd ~, which starts us off at our user home directory. I often follow this with the pwd command which tells me exactly where I am. This prevents me from getting lost:
$ cd ~ michael@MJL-3A-VISTA64 ~ $ pwd /c/Users/michael michael@MJL-3A-VISTA64 ~ $
Now, using a series of cd commands, we follow the path toward our project. You can do this in one long command, but I will be taking one step-at-a-time to reduce the chance of a big mistake.
michael@MJL-3A-VISTA64 ~ $ cd Documents michael@MJL-3A-VISTA64 ~/Documents $ cd "Visual Studio 2008" michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008 $ cd Projects michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008/Projects $ cd Assignment_1 michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008/Projects/Assignment_1 $ cd Assignment_1 michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008/Projects/Assignment_1/Assi gnment_1 $
If you issue an ls command (list files and folders), you will see the files that you knew were there all along:
$ ls Assignment_1.cpp Debug Assignment_1.vcproj ReadMe.txt Assignment_1.vcproj.mjl-3a-vista64.michael.user
On a Mac, using an Eclipse/Java environment, the listing would look a little different because we would have initialized the repo from our Assignment_13 project's src directory which has only one .java file in it (based on my single-file project):
michael-loceffs-iMacsrc bear$ ls Foothill.java michael-loceffs-iMac:src bear$
Creating the Repository
The project folder is where the repository, or repo, will live. That's why we went there. We are going to create a repo by issuing the git init command, and thus create a new subdirectory named .git, within the project folder. Git uses the .git subdirectory for directing traffic in our project evolution -- it stores all the secret, but vital, data about our project's history. Let's issue the git init command, followed by an ls to list the files afterward.
$ git init Initialized empty Git repository in c:/Users/michael/Documents/Visual Studio 200 8/Projects/Assignment_1/Assignment_1/.git/ michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008/Projects/Assignment_1/Assi gnment_1 (master) $ ls Assignment_1.cpp Debug Assignment_1.vcproj ReadMe.txt Assignment_1.vcproj.mjl-3a-vista64.michael.user
That's interesting.
We don't see the new .git directory. The dot at the start of .git, makes it a hidden entity. If you issue the ls command with the -a (all) option, you will see it:
$ ls -a . Assignment_1.cpp Debug .. Assignment_1.vcproj ReadMe.txt .git Assignment_1.vcproj.mjl-3a-vista64.michael.user
Another detail you may have noticed is that the parenthetical, (master), is displayed after the directory name (end of line that starts "michael@MJL..." two screen shots above). It means that this is going to the master branch which is the main project effort. Any experimental or beta efforts will sprout from this branch and get their own branch names, distinct from master (like beta_3_47, hotfix_1, hotfix_2, etc.). After all, the purpose of Git is to enable a lot of people to do a lot of things to a project, which will result in many different versions and experiments. There will always be a master branch which represents the main direction of the project.
G2.4 The Status of the Repo
Untracked vs. Tracked Files
Every file in the directory of the repository -- which is your project folder -- has a status. The most boring status is Untracked. These are files that we simply don't care about for tracking, but are still needed by our IDE. They may be important for our program -- the executables, IDE files, etc., but they are not human-readable and/or they just don't matter for tracking purposes. Put another way, these untracked files can usually be recreated from the more important source files which are tracked. So, if we give someone else the tracked files (via a Git checkout, for example) they will be able to reproduce all the other, untracked files.
The files we want to track are .cpp files for C++, .java files for Java, .html and .css files for web design, .txt files that have documentation, and so on.
When we create a new repo, no files are tracked. We can see this by issuing a git status command:
$ git status # On branch master # # Initial commit # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.cpp # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/ # ReadMe.txt nothing added to commit but untracked files present (use "git add" to track)
To start tracking a file or files, we use the git add command. We can add an individual file or a group of files, using the wildcard character, *:
$ git add ReadMe.txt $ git add *.cpp
(The wildcard, also has its origin in Unix.) Nothing visible happens, but when we ask for a git status, we see the difference:
$ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: Assignment_1.cpp # new file: ReadMe.txt # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/
Those files moved up to the section called Changes to be committed. We only need to do this once. The files Assignment_1.cpp and ReadMe.txt are now going to be tracked for the weeks, months or years that the project lives (unless we manually remove them from the tracked files).
What happens if some of the files that we want to track, like Foothill.java or math_tools.cpp, are inside subfolders deeper than the directory we set as the repo home? That is not a problem We don't have to explain such minutia to Git. If we want to add all .cpp or all .java files to those being tracked, we do so by using the same sort of command. For the Java project, when we do a git add *.java, Git would find the file, even if it were further down the directory tree.
Staged Files and "commit"
This brings us to a another category of files: staged. When files were added in the last section, they were not placed in the repository. So far nothing from our project is in the repo. We moved them into a staging area, which means that they will be moved into the repository at the next commit action. A commit is an action that tells Git we are sure we want to make our recent changes more permanent; we want to officially add them to the repo. Doing so means that we will be able to return to the state of the project as it was in the staging area at the time of the commit. Sometimes this commit involves a change to only one line or a small bug-fix to the code. Other times, as in the current situation, it means we are adding an entire file full of new code that wasn't there before. Let's do it.
$ git commit -m "The original commit for the password project" [master (root-commit) 3cb52d4] The original commit for the password project 2 files changed, 136 insertions(+) create mode 100644 Assignment_1.cpp create mode 100644 ReadMe.txt
The -m option indicates that we want to add a comment describing the significance of this commit. The string that followed it will be in the tracking documentation. If you don't use the -m options, a text editor will be opened for you, and you'll be able to put all sorts of documentation into that editor. When you close the editor, the commit action will proceed, automatically.
Let's look at the status now.
$ git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/ nothing added to commit but untracked files present (use "git add" to track)
We see that the two staged files are not present in the status. Where are they? They are not in the untracked section, since they are being tracked. But neither are they in the staging area. They are checked-in safely, and everything is calm and quiet. This means that our current files in the VC++ or Eclipse IDE, which are being tracked, are identical to those in the repository. We can sleep well.
Updating the Project and Repository
What happens if we further edit one of the files? Say we make a change to the program. I'm going to change a line to require a slightly longer password (this is a small detail deep in the code of the password program we are tracking). Here is the line before my change:
// test for reasonable length if (length < 6 || length > 15) { cout << "Password must be between 6 and 15 characters.\n"; continue; }
and now I will make some changes, strengthening the requirement for passwords: they must be at least 7 characters long:
// test for reasonable length if (length < 7 || length > 15) { cout << "Password must be between 7 and 15 characters.\n"; continue; }
(I should be using a symbolic constant for the 6 and 7, so I don't have to change it in two places. -1 point for me!) I compile it, run it, fix a bug I introduced, recompile and run and I'm satisfied. I save the project and quit my compiler. Now, let's go back to the Git console and check on the status:
$ git status # On branch 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: Assignment_1.cpp # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/ no changes added to commit (use "git add" and/or "git commit -a")
We can see that there are "changes not staged for commit." This is yet another state (and and the last one today) that one of our project files can be in: modified but not staged. It simply means we are working on this file, but we are, for one reason or another, not ready to stage it for a commit. Maybe we are working on a problem and have not resolved it yet. Or perhaps we are experimenting with a new feature and we have not completed the minimal functionality needed to warrant staging it. At any rate, once we are ready to stage this file, we issue the git add command again:
$ git add Assignment_1.cpp michael@MJL-3A-VISTA64 ~/Documents/Visual Studio 2008/Projects/Assignment_1/Assi gnment_1 (master) $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: Assignment_1.cpp # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/
The status shows that Assignment_1.cpp is now staged, waiting for a commit. Let's do that now:
$ git commit -m "Stengthened length requirement for password to length 7." [master 42f6803] Stengthened length requirement for password to length 7. 1 file changed, 2 insertions(+), 2 deletions(-)
Now if we check the status, all is quiet again.
$ git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Assignment_1.vcproj # Assignment_1.vcproj.mjl-3a-vista64.michael.user # Debug/ nothing added to commit but untracked files present (use "git add" to track)
Incidentally, we can ask Git to stop pestering us about the untracked files by creating and editing an .ignore file in our repository folder. But we only have time in this section for the bare essentials. As you can imagine, we have not begun to scratch the surface.
- How do we recover a previous state of the project?
- How do we remove a file from the staging area?
- How do we overwrite our mess, if we have made some unproductive changes, with a clean copy from the repo?
- How do we branch our repo so as to allow a beta version of the software while continuing to allow a master branch to hold the current version for hot bug fixes?
- How do we merge different contributors' work?
- What GUI apps are available to help automate some of these tedious command-line tasks?
- How do we pull and push our repo from/to a remote server?
For the purpose of this brief intro we will not be able to answer these questions today. However, I will touch on the answer to a couple of them in the next section about GitHub, the remote public repository used for secure tracking and collaboration.