{ } Programming

Git explained properly: commits, branches and merges

Git's core concepts explained clearly: staging area, commits, branches, merges and remotes, with the essential commands you need for everyday work.

Git is the most widely used version control tool, and also one of the most feared by beginners. The reason is that many people learn it as a sequence of commands to repeat by heart, without understanding what happens underneath. When something goes wrong, panic is inevitable. Yet Git's mental model is surprisingly simple: once you understand it, even the strangest commands start to make sense.

Why you need version control

Without version control you end up with folders called project-final, project-final-2, project-final-really. Git solves three concrete problems:

  • History: every saved change can be recovered, with author, date and reason.
  • Experimentation: you can try an idea on a separate branch without touching working code.
  • Collaboration: several people work on the same files and Git helps combine their work.

Git's three areas

The key point is that files in Git pass through three zones:

Area What it contains Typical command
Working directory Files as you see and edit them (you edit with your editor)
Staging area Changes chosen for the next commit git add
Repository The history of saved commits git commit

The staging area (also called the index) confuses many people at first, but it is very useful: it lets you decide exactly what goes into a commit. If you fixed a bug and also edited the documentation in the meantime, you can make two separate commits, each with its own meaning.

What a commit really is

A commit is a complete snapshot of the project at a given moment, together with a message, an author and a reference to the previous commit (the "parent"). Each commit is identified by a hash, a long hexadecimal string computed from its content. This means a commit cannot be altered without changing its identity: the history is protected against silent changes.

The basic flow is always the same:

git status                 # what has changed?
git add file1.py file2.py  # choose what to save
git commit -m "Fix VAT calculation on discounts"
git log --oneline          # view the history

Get used to running git status constantly: it is the command that always tells you where you are.

Branches: lightweight lines

A branch in Git is not a copy of the project: it is simply a movable label pointing to a commit. When you make a new commit on a branch, the label moves forward. That is why creating a branch is instant and costs nothing.

git switch -c new-feature   # create the branch and move to it
# ... changes and commits ...
git switch main             # go back to the main branch

There is also a special label, HEAD, which shows where you are right now. When you hear about a "detached HEAD", it means you are looking at a commit directly, without being on a branch: commits made in that state risk being lost unless you create a branch.

Merge: combining work

When the feature is ready, you integrate it into the main branch:

git switch main
git merge new-feature

Two things can happen. If main has not changed in the meantime, Git simply moves the label forward (fast-forward). If both branches have new commits, Git creates a merge commit with two parents.

A conflict occurs when the two lines of development changed the same lines in different ways. Git does not choose for you: it marks the file with the <<<<<<<, ======= and >>>>>>> delimiters. You decide the correct version, remove the delimiters, then run git add and git commit. A conflict is not an error, it is a question.

Remotes: working with others

A remote is another copy of the repository, usually on a server. The essential commands are three:

  • git fetch downloads new commits from the remote without touching your work;
  • git pull downloads and integrates them into the current branch;
  • git push sends your commits to the remote.

A healthy habit is to run git fetch and look at what changed before integrating, rather than running git pull blindly.

Undoing without damage

Much of the fear of Git comes from worrying about losing work. Some safety tools:

  1. git restore file discards unsaved changes to a file (these really are lost).
  2. git revert <commit> creates a new commit that undoes an earlier one: safe even on shared branches.
  3. git reflog shows every position HEAD has recently been at: it is the safety net for recovering commits that seem to have vanished.

The general rule: what has been committed is almost always recoverable; what was never committed is not. Commit often.

In short

  • Git has three areas: working directory, staging and repository; git add and git commit move changes between them.
  • A commit is a complete, immutable snapshot of the project, identified by a hash.
  • A branch is just a label pointing to a commit: creating one is free.
  • Merge conflicts are questions you answer, not errors.
  • Commit often and remember git reflog: saved work is almost always recoverable.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. With degrees in computer science and psychology, he combines technical analysis with an understanding of the human factor.

Read also