Git is a version control system: it records the history of every change to a project's files, so you can see what changed, when and why, go back to any earlier point, and work on the same code with other people without overwriting each other's work. Every Git clone carries the full history, which is why most operations are fast and work offline.

GitHub, and similar services such as GitLab, are something else: a place to host the shared copy of a repository online, with features like pull requests, code review and CI on top. Git is the tool that runs on your machine; GitHub is a host for your Git repositories. Below are the essential Git commands, in roughly the order you'll need them day to day.

Short answer: The essential Git commands are git init or git clone to start, git status to see where you are, git add and git commit to record changes, git log and git diff to inspect history, git switch and git merge for branches, and git pull and git push to sync with GitHub. To undo changes, git restore and git reset --soft are safe for local work, and git revert is the right tool for commits you've already pushed.

init, commit, a branch and a merge, the log, and undoing a pushed commit with revert.

Before you start: install Git and introduce yourself

On Ubuntu 24.04, Git installs with one command. Then set your name and email, because they're recorded on every commit:

bash
sudo apt install git
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

The last line names the default branch of new repositories main, which is the most common convention today.

Diagram of the four places a change lives in Git: working tree, staging area, local repository and remote, with git add, commit and push between them
Every Git command moves work between these four places.

Understand Git's three areas

Most Git confusion comes from not knowing these three areas:

  • Working tree: the files you see and edit.
  • Staging area (index): the changes you've selected for the next commit.
  • Repository: the commit history, stored in the .git directory.

The cycle is always the same: edit a file, stage it with add, and record it in history with commit.

Everyday Git commands

Starting a project: init or clone

For a brand-new project, create a repository inside its folder:

bash
mkdir my-project && cd my-project
git init

If the repository already exists somewhere like GitHub, clone it. This brings down the full history and sets up a remote named origin automatically:

bash
git clone git@github.com:user/my-project.git

status: always check where you are first

bash
git status

This tells you which branch you're on, which files have changed, which are staged and which Git isn't tracking at all. Make a habit of running it before every add and commit.

add and commit: recording a step

bash
git add index.php          # a single file
git add src/               # a directory
git add -p                 # hunk by hunk, prompting for each change
git commit -m "Validate email before saving the contact form"

git add -p is underused but extremely handy: when you've made two unrelated changes in one file, you can commit each one separately.

Write commit messages for whoever reads them a year from now: what changed and why. "fix" and "update" tell them nothing.

log and diff: viewing history and changes

bash
git log --oneline            # one commit per line
git log --oneline --graph    # with a branch graph
git diff                     # changes not yet staged
git diff --staged            # staged changes that will go into the next commit
git diff main..feature       # difference between two branches

Run git diff --staged before every commit. It regularly stops a stray dd() or a test password from landing in the repository.

branch and switch: parallel work without the mess

A branch is a separate line of work. Create one for each feature or bug fix so main always stays healthy:

bash
git branch                    # list branches
git switch -c feature/login   # create a new branch and switch to it
git switch main               # go back to main
git branch -d feature/login   # delete a merged branch

In recent Git versions, switch replaces the branch-related uses of checkout and is easier to read. checkout still works, but it does several unrelated things, which is exactly what makes it confusing.

merge: combining branches

When the work on a branch is done, switch back to main and merge it:

bash
git switch main
git merge feature/login

If both branches changed the same line of the same file, you get a conflict. Git marks the file with <<<<<<<, ======= and >>>>>>>; fix it by hand, remove the markers, then:

bash
git add path/to/file
git commit

remote, push and pull: working with GitHub

bash
git remote -v                                         # list remotes
git remote add origin git@github.com:user/repo.git   # add a remote to a repo created with init
git push -u origin main                               # first push, linking the branch to origin
git push                                              # subsequent pushes
git pull                                              # fetch and merge other people's changes

git pull is really two operations: fetch (download the changes) followed by a merge. If you want to see what arrived first, run git fetch and review it with git log --oneline main..origin/main.

Connecting to GitHub with git@github.com:… URLs requires an SSH key; creating one is covered in SSH keys and connecting to a server.

Undoing changes without losing work

Git can recover from almost any mistake, as long as you use the right command. Read this section carefully.

restore: discard changes to a file

bash
git restore index.php            # revert the file to the last commit (changes are lost)
git restore --staged index.php   # unstage; the changes stay in the file

Be careful: git restore without --staged permanently deletes uncommitted changes, and Git has no way to get them back.

reset --soft vs. reset --hard

Say you committed too early and want to change the message or add a file:

bash
git reset --soft HEAD~1

The commit is removed, but all its changes stay staged. This is completely safe.

This one, however, needs care:

bash
git reset --hard HEAD~1

--hard removes the commit and also throws away every uncommitted change in the working tree. Two rules:

  • Before reset --hard, run git status and make sure there's nothing uncommitted you still need.
  • Don't reset commits you've already pushed. Your history will diverge from everyone else's, and pushing will require --force, which wipes out other people's work.

If you lose a commit to a reset, git reflog lists where HEAD has recently been, and you can usually recover it from there.

revert: the safe way to undo pushed commits

revert doesn't erase history; it creates a new commit that exactly cancels out an earlier one:

bash
git log --oneline
git revert a1b2c3d
git push

On a shared branch, this is always the right choice.

stash: shelve unfinished work

You're mid-task and need to jump to another branch quickly:

bash
git stash push -m "half-done login form"
git switch main
# ... urgent work ...
git switch feature/login
git stash pop

git stash list shows everything you've stashed. Don't use stash as long-term storage; if the work will take more than a day, a temporary commit on its own branch is safer.

.gitignore: what should never go into the repository

A .gitignore file at the project root tells Git which files to ignore. A sensible one for a Laravel project:

.gitignore
# Dependencies; rebuilt by composer and npm
/vendor/
/node_modules/

# Secrets and local settings
.env
.env.*
!.env.example

# Build output and temporary files
/public/build/
/storage/*.key
*.log

# Editor and OS files
.idea/
.vscode/
.DS_Store

Two important points:

  • .gitignore only affects files that aren't tracked yet. If .env was already committed, remove it from the repository with git rm --cached .env.
  • If a password or key was ever committed and pushed, removing it in the next commit isn't enough; it's still in the history. Rotate that secret.

Git commands cheat sheet

Task Command
Create a new repository git init
Clone an existing repository git clone <url>
Check status git status
Stage changes git add <file> or git add -p
Commit git commit -m "message"
Compact history git log --oneline --graph
Unstaged / staged changes git diff / git diff --staged
Create and switch to a branch git switch -c <name>
Switch to an existing branch git switch <name>
Merge a branch into the current one git merge <name>
List / add remotes git remote -v / git remote add origin <url>
Push / pull git push / git pull
Discard changes to a file git restore <file>
Unstage a file git restore --staged <file>
Undo last commit, keep changes git reset --soft HEAD~1
Undo commit and discard changes (dangerous) git reset --hard HEAD~1
Undo a pushed commit git revert <hash>
Stash and restore work git stash push / git stash pop
Find a lost commit git reflog

Frequently asked questions

What is the difference between Git and GitHub?

Git is a version control tool that runs on your own machine and keeps the history of a project's changes. GitHub is a service that hosts the shared copy of a Git repository online and adds features such as pull requests, code review and CI.

What is the difference between git pull and git fetch?

git fetch only downloads new changes from the remote and leaves your branches untouched. git pull is a fetch followed by a merge into your current branch, so if you want to see what arrived before integrating it, fetch first and decide afterwards.

How do I undo the last commit without losing my changes?

Run git reset --soft HEAD~1: the last commit is removed, but all its changes stay staged so you can commit them again properly. Only do this for commits you haven't pushed yet.

What is the difference between git reset and git revert?

reset moves the branch back and removes commits from it, so it's only suitable for local, unpushed work. revert leaves history intact and adds a new commit that cancels out an earlier one, which makes it the right choice for shared branches and pushed commits.

How do I remove a committed file from Git but keep it on disk?

Run git rm --cached followed by the file name, add the file to .gitignore and commit. If the file contained a password or key and was pushed, it remains in the history, so rotate that secret.

Wrap-up

For everyday Git you need little more than a dozen commands: status, add, commit, log, diff, switch, merge, pull and push. What separates a confident Git user from a beginner is knowing the ways back: restore and reset --soft for local work, revert for anything already pushed, and constant caution with reset --hard. Make small commits with clear messages, create a branch for each piece of work, and put .env in .gitignore from day one.

If you've just got a server and want to deploy your project to it from Git, essential Linux commands for servers is a good next step.