If you write code on more than one computer, work with other developers, or have ever lost work to a bad save, you need Git. Git is a version control system — a way to save snapshots of your project over time, with a full history of every change. It is one of those tools that feels intimidating until you internalise about ten commands, and then you cannot imagine life without it.
This article is a plain-English introduction for absolute beginners. No prior version control experience required. By the end you will know how to save your work, undo a mistake, branch off to try an idea, and merge your work back together.
What Git actually does
Git stores your project's history as a series of commits. Each commit is a snapshot of every file in your project at a specific moment, with a description of what changed. You can jump backwards and forwards through history, compare any two snapshots, and branch off to try something risky without affecting the main line of work.
Git is distributed, which means every developer has the full history on their machine. There is no central server that can go down and lose your work. You can commit, branch, and merge entirely offline, then push your changes to a remote (GitHub, GitLab, Bitbucket) when you have an internet connection.
The three areas
Before we touch a single command, you need to understand Git's mental model. Git has three areas, and most operations move files between them.
- Working directory — your actual files on disk. This is where you edit code.
- Staging area — a holding zone for changes you are about to commit.
- Repository — the database of commits. Once something is here, it is permanently saved.
The flow is: edit in the working directory, stage the changes you want, commit them to the repository. Each step is a separate command, which is why Git feels verbose at first.
Installing and configuring Git
On macOS, install Xcode Command Line Tools: xcode-select --install. On Windows, download Git for Windows from git-scm.com. On Linux, use your package manager: sudo apt install git.
Once installed, set your name and email. Git attaches these to every commit:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
Use the same email as your GitHub (or GitLab) account. It links your commits to your profile.
Your first commit
Open a terminal in your project folder and type:
git init
That creates a hidden .git folder — the repository. Your files are not yet tracked. Add them with:
git add .
git commit -m "Initial commit"
The git add . stages every file in the current directory. git commit -m "..." creates a snapshot with the message you supplied. That is the whole loop. Edit, stage, commit, repeat.
Checking status and history
Two commands you will run a hundred times a day:
git status
git log
git status shows what is staged, what is modified, and what is untracked. git log shows the commit history — who did what, when, with which message. Press q to exit the log viewer.
For a more readable log:
git log --oneline --graph --decorate
That gives a compact one-line-per-commit view with a graph of branches.
Undoing things
This is the part that terrifies beginners, because Git makes it possible to lose work. In practice, undoing in Git is much safer than undoing in most other tools, because almost every operation can be reversed.
- Undo a file you have not staged yet.
git checkout -- file.txtresets the file to the last committed version. - Unstage a file you accidentally added.
git reset HEAD file.txtremoves it from the staging area but keeps your changes. - Amend the last commit message.
git commit --amend -m "Better message". Use this if you have not pushed yet. - Revert a commit that has been pushed.
git revert <hash>creates a new commit that undoes the old one. This is safe to share.
The two commands people misuse are git reset --hard (which throws away uncommitted changes permanently) and force pushes. Avoid both until you understand exactly what they do.
Branching: the superpower
Branches are independent lines of development. You create one to try an idea, fix a bug, or work on a feature. Your main branch is usually called main (or master, in older projects).
git checkout -b feature-login
That creates a new branch called feature-login and switches to it. You can now commit freely without affecting the main branch. When you are happy with the work, merge it back:
git checkout main
git merge feature-login
If you no longer need the branch:
git branch -d feature-login
Branches are cheap in Git. Create them for anything that takes more than ten minutes. The discipline of "one branch per feature" saves hours of integration pain later.
Working with a remote
GitHub, GitLab, and Bitbucket all speak Git. To push your local repo to a remote, first create an empty repo on the service, then add the remote:
git remote add origin git@github.com:you/your-repo.git
git push -u origin main
From then on, git push sends your commits to the remote, and git pull fetches new commits from it. If you clone an existing repo, the remote is already set up for you.
Pull requests and code review
On a team, the typical workflow is: create a branch, commit your changes, push the branch, open a pull request on GitHub (or merge request on GitLab), get a code review, then merge. The pull request is a place for discussion — comments on specific lines, suggestions, automated checks. Once everyone approves, you click merge and the branch becomes part of main.
This is where GitHub adds real value over plain Git: a place to talk about code, run tests automatically, and gate merges on review. The combination is what most teams mean when they say "Git workflow."
Common pitfalls
- Committing large binary files. Git tracks diffs of text well but stores every version of a binary. A 50MB video file checked in once will balloon the repo forever. Use Git LFS or external storage.
- Committing secrets. API keys, passwords, .env files — never commit them. Rotate the key immediately if you do. Tools like
gitleakscatch them. - One massive commit. Break work into logical commits. "Add login form", "Validate email format", "Add tests". Easier to review, easier to revert.
- Committing on main. Always work on a branch. Even for solo projects. The five seconds it takes to branch saves hours of "oh no I broke main" cleanup.
- Force pushing without coordination. Never
git push --forceon a shared branch. It rewrites history and breaks everyone else's clones.
A more advanced thing: rebasing
When you have a feature branch with several commits, you can rewrite its
Further reading
Git is one of those tools where the official documentation is genuinely good. We recommend starting with the official Git book (free online) and using GitHub’s guides for the social side — pull requests, reviews, and collaboration workflows.
- Git official documentation — the documentation for Git itself, including the reference manual, every command, and short tutorials.
- Pro Git book — the free online edition of the Pro Git book by Scott Chacon and Ben Straub — still the best structured introduction to Git.
- GitHub Git learning resources — GitHub’s curated learning path for Git, covering the CLI, the desktop app, and the GitHub-specific collaboration features.
git rebase main replays your commits on top of the latest main, producing a linear history. It is a way to keep your branch tidy before opening a pull request.
Rebasing rewrites commit hashes, so never rebase commits that have been pushed and shared. The rule of thumb: rebase local-only branches, merge shared ones. If that sentence made no sense, do not worry — it will click the first time you have a messy git log and want to clean it up.
A note on commit messages
The message on each commit is the closest thing Git has to documentation. A good message says why you made the change, not what (the diff already shows the what). "Fix the bug where users could see other users' drafts" is great. "Updated code" is useless. Many teams adopt a convention like Conventional Commits (feat:, chore:, fix:) for machine-parseable history, but the underlying principle is the same: future you will read these messages at 11pm trying to figure out why a particular line changed. Be kind to that person.
FAQ
What is the difference between Git and GitHub?
Git is the version control tool, which runs on your machine. GitHub is a hosting service for Git repositories, with a web UI and collaboration features. You can use Git without GitHub, and GitHub without ever touching Git on the command line (via their desktop app).
How do I undo the last commit?
If you have not pushed: git reset --soft HEAD~1 keeps your changes staged. git reset HEAD~1 keeps them unstaged. git reset --hard HEAD~1 discards them entirely. If you have pushed, use git revert HEAD to create a new commit that undoes the last one.
What is the difference between git pull and git fetch?
git fetch downloads new commits from the remote but does not merge them. git pull is fetch followed by merge. Most of the time, git pull is fine. If you have uncommitted changes, fetch and merge manually to control the timing.
How do I see what changed in a commit?
git show <hash> displays the commit message and a diff of changes. git diff HEAD~1 shows what changed in the most recent commit.
Should I use the command line or a GUI?
Both are fine. The command line is universal across teams and platforms, and it is what most tutorials and Stack Overflow answers assume. GUI clients are friendlier when you are new and excellent for browsing visual history graphs. The command line gives you power and is universal. GUI clients like GitHub Desktop, Sourcetree, or the GitKraken client are friendlier for browsing history and resolving merge conflicts. Most developers use a mix.
Take a deep breath, commit your work, and never fear git status again.
Homework
Create a new folder on your computer called git-practice. Open a terminal there and:
- Run
git initand create three text files with anything in them. - Add and commit them one at a time, with three separate commit messages.
- Use
git logto see the history. - Create a branch called
experiment, edit one of the files, and commit. - Merge
experimentback into main. - Delete the
experimentbranch. - Push the whole thing to a new GitHub repo (you will need a free account).
That sequence takes about twenty minutes and exercises every command you will use day-to-day. If you can do it without panicking, you have passed Git 101.