A practical learning exercise for Git

A practical learning exercise for Git

How to get started with Git by using a simple code project.

Team checklist and to dos
x

Get the newsletter

Join the 85,000 open source advocates who receive our giveaway alerts and article roundups.

In an effort to get some practice using Git, I began reading the documentation and some articles here on Opensource.com, particularly Seth Kenlon’s introductions. Once I finished reading, it was time to do some actual practice.

Like many undergraduate computer science students, I've done programming homework and labs. I saved all of this work, so why not use this code to create a practice Git repository? Then, I could run the code and fix any problems, which would let me practice making commits and creating branches. By doing so I could demonstrate basic Git proficiency.

I'm not new to version control. I've used older tools, such as CVS and Subversion, and was once an administrator, many years ago, for Borland (now Micro Focus) StarTeam. However, my Git experience was limited to minor usage of Atlassian Bitbucket. I was not a Git Guru.

It was time to learn.

Assessing the old code

Before getting too comfortable with GUI tools and sites like GitHub and GitLab, I wanted to spend time on the command line in order to fully understand how Git works. I started by checking to see if Git was installed, so I tried to run the git command. However, it wasn't installed, but this problem is easy to fix using distribution package managers. For example, on Ubuntu you can run sudo apt install git to install this tool. On Fedora, sudo dnf install git gets the job done.

Once I ran the package manager, a quick check confirmed that Git was now installed:

$ git --version
git version 2.17.1

At this point, I located my old files and rearranged them into a directory structure that could work well. The files were from an assignment—Lab 2—for my CSC121 class. The objective was to code an application that plays the role of a gas station. The user had to select the fuel grade and number of gallons to purchase. The grade determined the cost per gallon, which was then multiplied by the number of gallons to produce the total purchase cost. I still had both the C source code and the compiled binary.

~/GIT/CSC121/lab2$ file *
Lab2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, not stripped
Lab2.c: C source, ASCII text

This source code is only 33 lines long. I was curious to know whether this binary, compiled over 20 years ago, would still execute.

~/GIT/CSC121/lab2$ ./Lab2
      GoGo Gas station
enter type of gas;r-regular;p-premium;s-super:

The fact that it succeeded is a testament to backward compatibility!

I began to think about what changes I could make to the code. I wanted to complete a few more tests first by seeing whether the code ran correctly. For instance, purchasing 10 gallons of premium gas resulted in:

p
enter quantity;# of gallons:
10
type of gas pumped:premium
price of premium gas per gallon:$1.30
your total cost is:$ 13.000000

My first thought was, "Wow, gas was cheap 20 years ago!" Given this simple test, I determined that I did have a small, useful code project to use as Git practice.

Setting up the repository

The first step in getting started with Git is to create a repository. I also configured a few things to get started, such as setting my identity for Git, defined by my user name and email address. To set my identity, I made sure that I was in the working directory that I intended to use, which in this case is my lab2 directory.

The command to create the repository is simple:

$ git init
Initialized empty Git repository in /home/alan/GIT/CSC121/lab2/.git/

A command that I use a lot today is git status, to check the status of a repo. Running this on my new repository results in:

$ git status
On branch master

No commits yet

Untracked files:
(use "git add <file>..." to include in what will be committed)

      Lab2
      Lab2.c

nothing added to commit but untracked files present (use "git add" to track)

The above results reveal important information. In this case, they tell me that I am currently on the master branch and that nothing has been committed. Git also lists the two files in my working directory as untracked, since they haven't been added. The next step is to add these files. 

Whether or not to add a compiled binary is a decision to make depending on your usage. Generally, binary files are stored in a Binary Repository and are not added to Git because Git cannot diff binary files. In my case, I wanted to hang on to this particular binary. I used the command git add to add both of these files to the repo.

The command doesn't produce any output, but checking status again reveals that Git no longer lists the files as untracked:

Changes to be committed:
(use "git rm --cached <file>..." to unstage)

      new file: Lab2
      new file: Lab2.c

After adding the files, I did a git commit, using the -m option to include a message:

$ git commit -m "Lab2 first commit"

That's it! The repository has been populated. Checking the status again reveals that all is well:

$ git status
On branch master
nothing to commit, working tree clean

To reinforce what I’d learned, I repeated this process a few times and soon was comfortable with the most common tasks involved with maintaining a repository. I had a handle on adding files with git add, and removing files with git rm. I also knew how to commit these changes. The next item to tackle was slightly more complex: git branch.

Using Git

A Git branch is used to separate work. This tactic is commonly used when new features are in development but need to be kept distinct until ready for general release.

I thought it would be good idea to create a branch called original to store the original files. This way, if I had different branches and was ready to merge back to master, I would not overwrite the old version. I did this with the git branch command, specifying the name of the new branch:

git branch original

This step duplicates the master to the new branch. To list the branches, I use the git branch command with no arguments. The asterisk indicates my active branch:

$ git branch
* master
  original

I use git checkout to look at my new branch. Once again, git branch uses an asterisk to indicate my active branch:

$ git checkout original
Switched to branch 'original'

$ ls
Lab2 Lab2.c

$ git branch
  master
* original

Earlier, I identified something in the original code that I wanted to change. So, to keep a new version organized while preserving the current code, I created another branch solely for an update called Fix2019. I made this my new active branch and removed the binary.

$ git branch Fix2019 master
$ git checkout Fix2019
Switched to branch 'Fix2019'

$ git rm Lab2
rm 'Lab2'

At this point, I edited my code to update the prices. Premium is definitely not $1.30 anymore, so I increased it to $2.75. The actual updated C code is shown below:

{
printf ("type of gas pumped:premium\n");
printf ("price of premium gas per gallon:$2.75 \n");
price=2.75*quantity;
printf ("your total cost is:$ %f\n",price);
}

I saved the file and tried to recompile:

$ cc Lab2.c -o Lab2

Great, it compiled! As a test, I ran the binary again and bought another 10 gallons of premium gas (remember 20 years earlier the total cost was $13.00).

$ ./Lab2
        GoGo Gas Station
enter type of gas;r-regular;p-premium;s-super:
p
enter quantity;# of gallons:
10
type of gas pumped:premium
price of premium gas per gallon:$2.75
your total cost is:$ 27.500000

Those ten gallons now cost $27.50! I might have to walk more!

The command git status summarizes all of the actions that I have taken:

$ git status
On branch Fix2019
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    Lab2

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:   Lab2.c

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        Lab2

I had to commit my changes to the Fix2019 branch. I added my updated code and the new binary using git add ., followed by a git commit:

$ git add .
$ git status
On branch Fix2019
Changes to be committed:

(use "git reset HEAD <file>..." to unstage)

      modified: Lab2
      modified: Lab2.c

$ git commit -m "Update gas prices"
[Fix2019 fba4b56] Update gas prices
2 files changed, 3 insertions(+), 3 deletions(-)
rewrite Lab2 (100%)

At some point along the way, I'll probably want to update the master branch with the newer code. This task is done by merging the branch containing the new code into the master branch. In this example, that means I would merge Fix2019 into the master branch. The merge is done from the branch receiving the new code, so first I must check out the master branch:

git checkout master

A grep for the old price showed that the master branch still contained the old code:

$ grep $1.30 Lab2.c
   printf ("price of premium gas per gallon:$1.30 \n");

So it’s time to merge. A final grep for the new price will confirm the merge:

$ git merge Fix2019

$ grep $2.75 Lab2.c
   printf ("price of premium gas per gallon:$2.75 \n");

Conclusion

This exercise helped me get started using Git. It only covers the basics of a local repository, and Git offers much more as a distributed version control system, but this was enough to get me started. Now it’s your turn. Find a simple project, load it into Git, and let the learning begin.

Topics

About the author

Alan
Alan Formy-Duval - Alan has 20 years of IT experience, mostly in the Government and Financial sectors. He started as a Value Added Reseller before moving into Systems Engineering. Alan's background is in high-availability clustered apps. He wrote the 'Users and Groups' and 'Apache and the Web Stack' chapters in the Oracle Press/McGraw Hill 'Oracle Solaris 11 System Administration' book. He earned his Master of Science in Information Systems from George Mason University. Alan is a long-time proponent of Open...