What Are Git and GitHub? An Introduction to Version Control
Why version control exists, how centralized and distributed tools differ and why Git and GitHub are not the same thing. We try distributed work by reading history and committing in a clone whose server is gone, then look at Git's short history, its place in DevOps and how the series is organized.
Version note: The commands in this post were tested with Git 2.54.
Guess First
All of your team's code lives in a repo on a single server. You have a copy of that repo on your own machine. One morning the server's disk dies and the repo is gone for good. Here is the question: can you still look at the project's history on your machine, who changed what and when? And can you make a new commit with no network at all?
We will see the answer in a real experiment shortly. The answer to this question is exactly what sets Git apart from the version control tools that came before it.
Why Version Control Exists
We have all seen this folder somewhere: report.docx, report_final.docx, report_final_v2.docx, report_final_v2_really_final.docx. That is version control done by hand, in its most primitive form. It gets out of control quickly even for a single document. In software you add hundreds of files, several developers and pieces of work that run in parallel.
A version control system gives a reliable answer to four questions. Who changed this file, when, and why? How do I get back to the version that worked last night? If two people work on the same file, how do we combine their changes? How do we keep the version that ships tomorrow apart from the one we are working on today?
Git answers them with records called commits. Each commit is a snapshot of the whole project at that moment; it carries an author, a date and a message that answers the "why". Line the commits up one after another and you get the project's history. Think of save points in a game: you can go back to any of them and take a different path from there.
Centralized vs Distributed Version Control
The popular tools before Git, CVS and Subversion (SVN), were centralized. The full history lived on one server. A developer's machine only had the latest version of the files. To look at history, make a commit or even see an old version of a file, you had to talk to the server. When the server went down, the team stopped; when its disk died, the history died with it.
Git is a distributed version control system. When you clone a repo you get not just the latest files but the entire history: every commit and every version of every file. Technically there is no difference between the repo on the server and the repo on your laptop. The server is simply the copy the team has agreed to use as its meeting point.
Let's try the opening question. If you have not installed Git yet, don't worry: installation is the topic of the next post, so for now just watch. We have a small repo called bookstore with two commits, and it plays the role of the server:
# Copy the repo from the "server" to your own machine
$ git clone bookstore ada-laptop
Cloning into 'ada-laptop'...
done.
# The server is suddenly gone
$ rm -rf bookstore
$ cd ada-laptop
$ git log --oneline
fae4454 (HEAD -> main, origin/main, origin/HEAD) Add shopping cart
29f27c8 Add README and book list
We deleted the server, yet git log showed the full history, because that history already lives in the .git folder inside ada-laptop. The origin/main part is the last known state of the server; we will look at it closely in the post on remotes. A command that has to talk to the server fails, of course:
$ git fetch
fatal: '/.../bookstore' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Committing, though, does not need the server:
# After adding a line to README.md
$ git add README.md
$ git commit -m "Mention the currency in README"
[main cec2371] Mention the currency in README
1 file changed, 2 insertions(+)
$ git log --oneline
cec2371 (HEAD -> main) Mention the currency in README
fae4454 (origin/main, origin/HEAD) Add shopping cart
29f27c8 Add README and book list
Our new commit lives locally; origin/main is still where it was. When the server comes back, we push this commit to it. So the answer to both opening questions is "yes". That is what being distributed means in practice: you keep working on a plane, on a train or while the server is down for maintenance, and every clone is also a full backup.
Git and GitHub Are Not the Same Thing
This is the pair beginners mix up most often. Git is an open source command-line tool you install on your machine. It manages commits, branches and history, and it does not belong to any company. GitHub is a web service that hosts Git repos. You keep your repo there, and on top of it you get features built for teamwork: pull requests, code review, issue tracking, CI/CD with GitHub Actions and access management.
An analogy: Git is the camera, GitHub is the photo-sharing site where people comment on your pictures. You don't need the site to take a photo, but you need to put it somewhere to share it with your team.
GitHub is not the only option, either. GitLab, Bitbucket and Microsoft's Azure DevOps (with Azure Repos inside it) are popular services that do the same job. If you want to host it on your own server, there is the self-managed edition of GitLab, plus options like Gitea or Forgejo. All of them run the same Git underneath, so everything you learn in the Git part of this series applies to all of them. GitHub-specific topics (pull requests, branch protection, tokens) get their own posts, with GitHub's name on them.
A Short History
Git was born for the Linux kernel. In the early 2000s the kernel developers used a commercial tool called BitKeeper. When the free license was withdrawn in 2005, Linus Torvalds decided to write his own tool, and the first version of Git appeared in April 2005. The goals were clear: it had to be fast, cope with thousands of developers working in parallel and guarantee that history could not be silently corrupted. Junio Hamano has maintained the project since July of that year.
GitHub opened in 2008, and that is largely what took Git out of the kernel world and turned it into everyone's everyday tool. Microsoft bought GitHub in 2018. On the Git side, the 2.x line that started in 2014 is still going. A new feature release (2.N.0) comes out roughly every 10–13 weeks, with maintenance releases carrying bug and security fixes in between. At the time of writing the latest stable release is Git 2.56.0, released on September 28, 2026.
Git 3.0 is on the horizon. Changes planned for 3.0 include main as the default branch name, SHA-256 hashes for new repos, a new ref storage format called reftable and Rust becoming mandatory for the build. The official documentation has no firm date yet, so I am not giving one. We will cover these plans in detail in the last post of the series.
Where Git Fits in DevOps
This series sits in the DevOps category of the blog because almost everything in a modern delivery pipeline starts with a commit. You push a branch, the CI server notices and runs the tests. When a pull request is merged, the CD side moves the application to a test environment. When you create a tag, the release gets packaged and shipped. In projects that define their infrastructure as code, even the server settings live in a repo, and every change to them is, again, a commit.
So knowing Git well is not just about not losing your own code. It is also the basis for understanding why a pipeline was triggered, which commit went to production and which change brought in a bug. GitHub Actions gets its own series later; this series builds a solid Git foundation.
How This Series Is Organized
The series is an expanded, up-to-date version of the "Git & Github" playlist on my YouTube channel. It keeps the order of the videos: the curriculum and what Git & GitHub are, the repo and the first steps, log and tracking changes, branches, conflicts, remotes and GitHub, and finally advanced topics such as reset, revert, restore, cherry-pick, stash, rebase and squash. Each video becomes one or more posts here.
The first block, posts 1–25, is the core. We use current Git and modern commands: git switch to change branches, git restore to restore files. Whenever it matters, I will point out the git checkout forms you will see in older posts and StackOverflow answers. The second block, posts 26–29, covers how Git evolved across versions: "this is how we used to do it, this is how we do it now" from Git 2.23 to today, and getting ready for Git 3.0.
All examples move forward in a single small project, a bookstore repo called bookstore. The team has two people: Ada and Alan. The code is deliberately simple, because the subject is Git, not JavaScript. The commands in these posts were actually run with Git 2.54, and the outputs were copied from those runs. Instead of pushing to GitHub for real, the examples use a local bare repo that stands in for the repo on GitHub; I describe the account and UI steps in the text.
Common Pitfalls
The first pitfall is treating Git and GitHub as the same thing. You will often hear someone say "I installed GitHub" when they installed Git, or "I uploaded it to Git" when they pushed to GitHub. Knowing the difference helps even when you read error messages: a line starting with fatal: is written by Git on your machine, while lines starting with remote: come from the server on the other end.
The second is thinking of Git as an automatic backup tool. Git only protects what you commit. A change you have not committed goes away with your disk. Work you have committed but not pushed lives only on your machine.
The third is leaning on a GUI or your IDE's buttons without learning the concepts. Buttons are comfortable for everyday work, but in the middle of a conflict or after a wrong reset, a button will not save you if you don't know what is going on. In this series we do everything on the command line; once you understand the commands, the tool you use stops mattering.
The fourth is turning the repo into a dumping ground. Passwords, API keys, large binary files and build output should not go into the repo. Committing a password and deleting it later is not enough, because it stays in the history. We will talk about how to prevent that in the .gitignore post.
A Small Experiment
★☆☆ Think of a project you work on now or worked on in the past. Where did the code live, how did you look at history, what happened when two people changed the same file? Try writing down that project's answers to the four questions from the start of this post.
★★☆ Pick two hosting services you use or are curious about (GitHub, GitLab, Bitbucket, Azure DevOps). In both, find where pull requests (merge requests on GitLab) and CI live. Try to separate which concepts belong to Git and which belong to the service.
★★★ If you have a machine with Git installed, repeat the experiment above yourself: create a small repo, clone it, delete the original and try git log and a new commit in the clone. If Git is not installed, come back after the next post.
In the next post we install Git on macOS, Windows and Linux, check the version with git --version and make the first settings that every repo will benefit from: your name, your email, why the default branch should be main and which file the settings live in.