At Oak City Labs we develop using a particular stack of technologies we are not only comfortable with, but believe to be the most effective tools in solving whatever challenges come our way. Too often when a developer says “We use X framework or Y library”, it sounds like utter gibberish and has no real meaning to non-technical people. This disconnect is the inspiration for my blog series: Non Technical Overviews of Technical Things.
Welcome back to my series of non technical overviews of technical things. This week I’ll be educating you on the powerful yet soothing nature of Git, a modern version control software. According to the Git docs, version control is “a system that records changes to a file or set of files over time so that you can recall specific versions later.” Sounds useful, right?
You may find version control useful if you have ever found yourself saying any of the following:
- “Oh #&(@ I ‘accidentally’ deleted EVERYTHING!!!”
- “Oh #&(@ I accidentally deleted EVERYTHING!!!”
- “What did version 220.127.116.11.2.10.549.1 of this file look like?”
- “Who made this change to this file?”
- “How can my team make changes to the same file without overwriting each other’s work?”
- “Do we backup our files?”
Intrigued? Great! Proper use of version control is one of the easiest and most efficient ways to keep your projects organized. Now a twist on that old familiar story to help explain things…
You’re A Web Developer, Charlie Brown
Chuck, Patty and Linus are working to build a website together. Chuck is a graphic artist, while Patty and Linus are developers.
The trio decides to use Git to organize and store their project. We will visualize their Git process using a sticky note board, a la realtimeboard.com. For clarity, we’ll match their sticky note colors up with their shirt colors: Green for Patty, Yellow for Chuck and Red for Linus.
Step 1: Set up Git
A nice aspect of Git is that it allows you to store your main project files anywhere. Git has a concept called a ‘repository’ which you can think of as the main storage location. In this example, it will be the whiteboard, but in real life, it can be any computer with the ability to store files. The most popular ‘hosting as a service’ platforms are Github and Bitbucket. For people who prefer to host the files themselves, Gitlab is a trusted option.
With Git, each person working on the project maintains a copy of all the project files at all times. The remote repository is a copy of the project from which all others pull from. When someone finishes a task in their local repository, they will push it up to the remote repository, and when they want to make sure they have the latest versions of all files, they pull down from the remote repository.
To start their project, they store one file on their remote repository:
- index.html – The main website file
Here is a visual representation of Team Peanuts’ Git usage for their project:
Step 2: Assign tasks
Now that the team has set up their remote repository, they choose tasks for each of them to work on.
Step 3: Setup for development
Now that the team has decided what they will work on, it’s time to start developing! Since the project is currently only stored on the remote repository, all three of our favorite character use git clone to create a clone, or an exact copy, of the remote repository. Now Chuck, Patty and Linus are all set up and ready to go!
Step 4: Development!
Being the efficient, diligent team they are, the Peanuts gang all get to work immediately doing what they do best! Chuck gets to work on the website icon, while Linus and Patty begin coding.
While Chuck is busy creating the website graphics in Adobe Illustrator, Patty and Linus each work on their copy of the index.html file, which was retrieved from the remote repository and acts as the main code file for their website.
Step 5: Sharing Work
Patty finishes her work first. Since she edited index.html, she needs to make sure her teammates get the very latest version of that file. Since the Peanuts team project is structured where each of the three characters’ local repositories (clones of the remote repository) only receive files from the remote repository, Patty has to push her changes up to the remote repository for her teammates to see.
To communicate with a Git repository, local or remote, you have to package your code changes in a commit. Think of a commit as an envelope containing all the changes that have been made recently. As soon as a commit is created, any changes made after that will fall into the next commit envelope.
Patty bundles her index.html changes into a commit called “Add boilerplate page layout”. Now, her local repository has been notified of these changes and can communicate to the remote repository whenever Patty is ready.
Since Patty works quickly, she goes ahead and pushes, or shares, her commit with the remote repository. In practice, Patty could send one push with many commits to the remote repository.
Before Patty pushes her files from local to remote, the Git board looks like this:
After pushing, the Git board now looks like:
At this point, Patty has completed her job and it’s up to Chuck and Linus to update their local repositories to mirror the remote repository and remain up-to-date.
Step 6: Sharing Work Pt. 2 // Updating Local Repositories
Right now, Chuck and Linus’s repositories are outdated. They lack the changes that Patty made. That’s alright for Chuck, though. His work does not touch the same files as Patty, so he’s not worried. He bundles his website icon in a commit.
Now that his local repository has the commit, Chuck is ready to push his local repository changes to the remote repository.
Chuck cannot do that, though. Why? Because Git would reject his commit. Git would say “Chuck, you don’t have the latest files. Your local repository is not in sync with the remote repository. Pull down the latest files before you try to push your changes.” Okay, Git wouldn’t actually say that…but it does reject his commit. How does Git know Chuck’s local repository is outdated? Magic. Also, because Git tracks every change in the history of the project, and it sees that his latest commit is one commit ahead of the latest commit on the remote repository. In order to make sure the project remains logically sound, Git requires that all local repositories are up-to-date with the remote repository before sending new commits.
Chuck pulls the latest code from the remote repository. To perform this operation, his local repository pulls down all of the commits that Chuck doesn’t have. Chuck can now push his icon, so he does.
Step 7: Merge Conflict Resolution
So far, all has been fine and dandy. Patty and Chuck were working on separate files, so there were no conflicts when Chuck’s commits were laid on top of Patty’s. But Linus has been working on the same index.html file as Patty, and now Linus is two commits behind the remote repository (one Patty commit, one Chuck commit).
Let’s say Linus finishes his work and bundles it in a commit envelope titled “Website spinning.” We already know he won’t be able to push, as we saw with Chuck, until Linus pulls the latest commits from the remote repository. Linus does so.
!!! Oh no !!! CONFLICTS DETECTED. What happened? Patty and Linus edited the same file. This means in order for Linus’ work to be applied on top of the commits from remote, any conflicts that arose from editing the same lines in index.html must be fixed before Linus can push his work to remote. In about 90% of cases, Git will actually be able to automagically fix these conflicts without you having to do any extra work. The other ~10% of the time, however, require manual conflict resolution. To do this, Git will show you which parts of the files are in conflict so that you can go in and fix it yourself.
Luckily for Linus (and for you, blog consumer), Git handled all conflicts that arose with aplomb. Now that Linus’ local repository has the latest commits from remote AND has his latest local commit, Linus can push his code to the remote repository.
Voila! Now Patty and Chuck can pull the latest changes from the remote repository and tada! Everybody’s local repository is synced up with the remote repository, and website development is well on its way.
Here are the Git concepts I covered in this post, alongside the actual Git command you would use to perform such an action.
- Add – git add
- Commit – git commit
- Pull – git pull
- Push – git push
To create a local repository:
- If remote already exists:
- git clone <url>
- If remote doesn’t exist:
- git init
To create a remote repository:
- If using a provider such as Github or Bitbucket:
- Create one via their website
- If self-hosting:
- Create one the same as you would create a local repository
What We Learned
Git is an incredibly powerful tool that we only scratched the surface of in this post. There are far more sophisticated aspects like branching and rebasing that weren’t even mentioned.
If you want to get started with git, this simple guide is a great place to begin your journey. Until then, the doctor is out.