We’re building a tic-tac-toe game to illustrate the value of incremental learning when it comes to software development.
(See all the posts in this series.)
So far, we’ve made a lot of progress! We now have a working game that you can play on the command line!
As any developer knows, there’s always more you can do to improve your application. Today, we’ll learn some common workflow stuff that won’t change the application, but it will dramatically help us develop it.
Where we are so far
To date, our game lives only locally and can accept inputs from two players.
When one player wins or there are no free spaces left on the board, the game prints a message and quits:
In the next phase of development, we’re going to add more features like an AI to play against.
While the application seems simple now, it could get quite complex very quickly.
We’re gonna make mistakes
As things get more complicated, the likelihood that we’ll make mistakes increases. There’s a good chance we’re going to code ourselves into a corner at some point or make poor decisions along the way.
Since we know we’ll make mistakes, it would be nice to have a way to easily undo those errors and try something new.
Better yet, it would be awesome to have multiple copies of our application where we could work on new features on one copy while the main copy stays playable and usable.
Copies = a bad idea
We could easily accomplish this goal of multiple versions of our application by actually creating copies of the file on our computer.
You’ve probably seen something like this if you’ve worked in a corporate environment for any amount of time:
If we keep appending suffixes to the file name, then we end up with multiple versions, sure. But that’s hardly an optimal solution.
It ends up quite cluttered and unclear which version we actually want to work on. What’s the most recent update? Which version is stable and which is under development?
Enter Git
Git is a tool for version control of your projects. It’s one of the most important tools in software development today.
First developed by Linus Torvalds (yes, the same guy who created Linux) in 2005, Git allows you to maintain multiple versions of the same files on your computer without needing to rename the files.
Instead, Git maintains a history of the revisions you’ve made to your files, allowing you to roll back changes in time.
Git also enables the creation of “branches” where you can work on a file under development in parallel to the stable version of the file. While you do, Git maintains separate revision histories for the various branches.
You can then switch between branches depending on your needs.
- Need the stable, authoritative version of your application? Switch to the “master” branch.
- Want to work on a new feature that might break the application? Switch to a feature development branch.
- Ready to incorporate your new feature into the stable, authoritative version of the app? Merge the revisions from “development” into “master.”
It’s that simple. Let’s set it up!
Mini-step #1: Install git
This tic-tac-toe game is still an exercise in incremental learning and small experiments. So, I won’t tell you how to use git. I’ll just point you in the right direction on some experiments you might try with git.
The first mini-experiment is intalling git on your local computer.
Lucky for me, this isn’t a tutorial, so I won’t explain the intricacies of installing git on Windows, Mac, and Linux.
Do a little Googling to find out how to add git to your computer.
Try it now!
…
…
…
Did you install it?
If you installed it correctly, you should be able to do something like:
$ git --version git version 2.7.4
Mini-step #2: Initialize a git repository
Now, git doesn’t start tracking all the files on our computer automatically. You wouldn’t want it to!
Instead, we need to tell git which directory it should track for us. To do that, we need to initialize a git repository (a version-controlled directory) in the same directory as our tic-tac-toe game.
Try to figure it out on your own before looking at my answer!
…
…
…
(Hint: Did you know you can type man git
to see git’s documentation? That might help…)
…
…
…
To start a new repository:
$ git init Initialized empty Git repository in /home/bennett/Repos/testrepo/.git/
Mini-step #3: Track some files
Even though we’ve initialized a git repository, git won’t start tracking files in that directory until we explicitly tell it to.
Telling git about a file involves two steps:
- Add the file to git’s tracked files
- Commit any changes you’ve made (or make an initial commit of new files)
In our case, we need to tell git that ttt.py
exists and we want git to track changes to it. Then, we need to commit the initial version of the file to git.
When we make a commit, git requires us to add a little message about the changes we’ve made. For now, it’s okay to just say “Initial commit.” Writing good commit messages is a subject for a whole different post.
Try it on your own: Figure out how to add a file to git and how to commit changes to that file. Use Google and **man git**
to help!
…
…
…
$ git add ttt.py
$ git status On branch master
Initial commit
Changes to be committed:
(use "git rm --cached
new file: ttt.py
$ git commit -m "Initial commit" [master (root-commit) 1aae357] Initial commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ttt.py
Every time we make a change that we want git to remember, we’ll need to git add
and git commit
. This is a key pattern of software development.
If this is your first time using git, welcome to version control! You’re now tracking a file.
Mini-step #4: Experiment with making changes
Let’s get some practice using git. Remember, the best way to learn anything new is incrementally. So, let’s just do some tiny experiments.
Try this:
- Create a new file
git_test.txt
- Add and commit the file to the git repo
- Open
git_test.txt
and type a test message, then save the file - Add and commit the changes you just made to git
- See if you can print a log of your commits to the repository thus far
Go test it out! Mini-experiments like this are the best way to really understand and speak git’s language.
…
…
…
$ touch git_test.txt
$ git add git_test.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD
new file: git_test.txt
$ git commit -m "Add git_test" [master 148b921] Add git_test 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 git_test.txt
$ echo "Oh, what a beautiful morning!" > git_test.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add
modified: git_test.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git add git_test.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD
modified: git_test.txt
bennett:testrepo$ git commit -m "Add message to git_test" [master 8857a09] Add message to git_test 1 file changed, 1 insertion(+)
$ git log commit 8857a09c28848300ceaf4179409c97d3c826d8f5 Author: Bennett Garner <34491412+bennett39@users.noreply.github.com> Date: Wed May 1 12:01:20 2019 -0400
Add message to git_test
commit 148b92138a5dc7e800a3d2a3e01aa4757e1fdb18 Author: Bennett Garner <34491412+bennett39@users.noreply.github.com> Date: Wed May 1 12:00:17 2019 -0400
Add git_test
commit 1aae3573ff6b568af563178f50b79f03a38322de Author: Bennett Garner <34491412+bennett39@users.noreply.github.com> Date: Wed May 1 11:52:00 2019 -0400
Initial commit
Mini-step #5: Undoing changes
Let’s imagine you want to undo the changes you just made. Maybe you realized that creating git_test.txt
was a mistake.
Can you figure out how to rollback changes in git?
Try:
- Go back to when
git_test.txt
was an empty file (rollback the message) - Go back to before you created
git_test.txt
(back to the initial commit)
…
…
…
$ ls git_test.txt ttt.py
$ git log --oneline 8857a09 Add message to git_test 148b921 Add git_test 1aae357 Initial commit
$ git reset --hard 148b921 HEAD is now at 148b921 Add git_test
$ git log --oneline 148b921 Add git_test 1aae357 Initial commit
$ git reset --hard 1aae357 HEAD is now at 1aae357 Initial commit
$ git log --oneline 1aae357 Initial commit
$ ls ttt.py
By the end, you can see that git_test.txt
is actually gone from the folder on my machine! Git knew to remove the file when I rolled back to the initial commit.
Mini-step #6: Create branches
When you first initialize a repository, you’re automatically on the master version of your repository.
$ git branch * master
However, git makes it easy to create as many different versions of your repository as you want. Each version can exist for building new features, experimenting, different configurations, etc.
See if you can figure out how to:
- Create a new branch called
development
- Switch to the
development
branch - Add and commit a file called
branch_test.txt
to thedevelopment
branch - Switch back to the
master
branch — is the new file there? - Switch back to
development
— is the new file there?
Play around with these steps and create even more branches to switch between. Now, you’re beginning to see the magic of git.
…
…
…
(Hint: you can use man
here as well! Try man git branch
for specific help on branches.)
…
…
…
$ git branch * master
$ git branch development
$ git branch development * master
$ git checkout development Switched to branch 'development'
$ git branch * development master
$ touch branch_test.txt
$ git add branch_test.txt
$ git commit -m "Add branch_test" [development e2e4e4c] Add branch_test 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 branch_test.txt
$ git status On branch development nothing to commit, working directory clean
$ ls branch_test.txt ttt.py
$ git checkout master Switched to branch 'master'
$ git status On branch master nothing to commit, working directory clean
$ ls ttt.py
$ git checkout development Switched to branch 'development'
$ ls branch_test.txt ttt.py
Mini-step #7: Merge branches
When you’ve made a change on a branch, and then you want to incorporate that change into the master version, you’ll need to conduct a merge.
Try:
- Switch to the
master
branch - Merge in the changes from the
development
branch - Delete the
development
branch — we don’t need it anymore, now that it’s merged
…
…
…
$ git branch * development master
$ git checkout master Switched to branch 'master'
$ git merge development Updating 1aae357..e2e4e4c Fast-forward branch_test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 branch_test.txt
$ ls branch_test.txt ttt.py
$ git branch -d development Deleted branch development (was e2e4e4c).
$ git branch * master
Wrapping up
This post is getting long, so I’ll wrap up for now.
Needless to say, there are entire articles on how git works and the things you can do with it!
Most development teams at major companies use git to work on dozens of new features at a time, merging changes into the master branch as each feature is complete and fully tested.
Learning git is a critical skill for any modern software developer. It’s also incredibly useful even for your personal projects.
We’ll be using git to track all our changes to the tic-tac-toe game. In fact, I’ve already been using git without explicitly telling you. That’s how I’m able to track and share different versions of the code each day.
See you next time!
About Bennett
I’m a software developer in New York City. I do web stuff in Python and JavaScript.
Want to be updated when I release a new post? I have an email list you can subscribe to. I have nothing to sell, only free content to share with the community, no time wasters. I’d love to have you there.
Check out the complete list of all posts in this tic-tac-toe series.