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:

git shot

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:

git shot

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:

git shot

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:

git shot

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
Notice that "java workspace" will be just "workspace" if you used the defaults when you installed and ran Eclipse the first time.  Or, it might be "c++ workspace", or anything else you named it, if you were using C++ and named it such. Furthermore, the quotes surrounding "java workspace" will be needed later, if you have a folder that, like mine, has a space in its name.  That's why you see them around "java workspace" but none of the other folders. 

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
Side Note - The commands ls, cd, pwd, etc.  are all Unix commands.  So you are learning a little Unix as you study this tutorial.

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. 

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.