This guide is a structured summary of ThePrimeagen’s complete Git course, originally presented as a 4-hour video. The content covers two main parts: using Git as a solo developer and using Git effectively within a team. The goal is to provide a clean, readable reference for the core concepts, commands, and workflows, from initial setup to advanced techniques like rebasing, stashing, and handling conflicts.
Before using Git, you must configure it and understand its basic structure.
git add
, git commit
).git config
)Git configuration is stored in files. You can set configuration at different levels, but the most common are:
--global
: Applies to every repository on your system. Stored in your home directory.--local
: Applies only to the current repository. Stored in the .git/config
file of that repository.Essential Configuration Commands:
# Set your name globally
git config --global user.name "Your Name"
# Set your email globally
git config --global user.email "[email protected]"
# Set the default branch name to 'main' (modern standard)
git config --global init.defaultBranch main
git init
)A Git repository (or “repo”) is a project directory that Git tracks.
Create a directory for your project:
mkdir my-project
cd my-project
Initialize it as a Git repository:
git init
This command creates a hidden .git
directory. This directory contains the entire history and state of your project. Everything Git knows about your project is inside .git
.
The daily workflow for a solo developer revolves around three main commands.
A file in a Git repo can be in one of three main states:
git status
: Shows the current state of your repository, including which files are untracked, modified, or staged. It’s the first command you should run to understand what’s happening.
git add <file>
: Moves a file from the untracked/modified state to the staged state. This prepares it for the next commit.
# Stage a specific file
git add contents.md
# Stage all changes in the current directory and subdirectories
git add .
git commit -m "Your message"
: Takes all staged files and creates a new commit (snapshot) with them. The -m
flag allows you to provide a descriptive message.
git commit -m "feat: Add initial table of contents"
After committing, git status
will show a “clean working tree,” meaning no changes are pending.
To truly master Git, you need to understand how it stores information.
git log
)The git log
command displays the commit history. It has many useful flags:
--oneline
: Shows a condensed, one-line view of each commit.--graph
: Draws an ASCII graph showing the branch and merge history.--decorate
: Shows where branch and tag pointers (HEAD
, main
, etc.) are located.--parents
: Shows the parent commits for each commit, which is useful for identifying merge commits.Git’s data is stored as objects in the .git/objects/
directory. The three main object types are:
Key Insight: Git stores snapshots, not diffs. Each commit points to a full tree of the project’s state. It remains efficient by pointing to existing, unchanged blobs and trees from previous commits.
You can inspect these objects with the plumbing command git cat-file -p <hash>
:
# 1. Find the hash of your latest commit
git log --oneline
# 2. View the commit object
git cat-file -p <commit_hash>
# This will show the tree hash, parent hash, author, and message.
# 3. View the tree object
git cat-file -p <tree_hash>
# This will show the blobs and other trees in that directory.
# 4. View the blob (file content)
git cat-file -p <blob_hash>
Branches are what allow for parallel development.
A branch is simply a lightweight, movable pointer to a commit. It is not a copy of your project.
git branch
: Lists all local branches.git switch -c <branch-name>
: Creates a new branch from your current location (HEAD
) and switches to it. (The older command is git checkout -b <branch-name>
).git switch <branch-name>
: Switches to an existing branch.git merge
Merging integrates the changes from one branch into another.
How to Merge:
# 1. Switch to the branch you want to merge INTO
git switch main
# 2. Merge the other branch
git merge feature-branch
Rebasing is an alternative to merging for integrating changes.
git rebase
?Instead of creating a merge commit, git rebase
rewrites history. It takes the commits from your feature branch and replays them on top of the target branch’s latest commit.
The Process:
main
).The result is a linear history, which can be easier to read and revert.
How to Rebase:
# 1. Switch to the branch you want to update
git switch feature-branch
# 2. Rebase it ONTO the target branch
git rebase main
CRITICAL RULE: Never rebase a public branch that others are using (like main
). Since it rewrites history, it will cause massive problems for anyone who has pulled the old version. Only rebase your own local, private branches.
Git provides powerful tools for undoing changes.
git reset
: Moves the current branch pointer to a different commit.
--soft <commit>
: Moves the pointer but leaves all changes from the undone commits in the staging area. Useful for squashing or fixing the last commit.--hard <commit>
: Moves the pointer and discards all changes in both the staging area and the working directory. This is destructive and can cause data loss if not used carefully.git revert <commit>
: Creates a new commit that is the exact inverse of the specified commit. It undoes the changes without rewriting history, making it safe for public branches.
Most development involves collaborating via a central remote repository like GitHub.
origin
.Standard Collaboration Workflow:
git clone <your_fork_url>
.upstream
: git remote add upstream <original_repo_url>
.git push origin <your-branch>
.upstream
repository.git fetch <remote>
: Downloads all changes from a remote repository but does not integrate them into your local branches.git pull <remote> <branch>
: Is equivalent to git fetch
followed by git merge
. It downloads and merges changes in one step.git push <remote> <branch>
: Uploads your local branch’s commits to the remote repository.reflog
: Your Safety Netgit reflog
(reference log) tracks every movement of HEAD
. If you accidentally reset --hard
and think you’ve lost a commit, reflog
will show you where HEAD
was, allowing you to find the “lost” commit hash and recover it (e.g., by cherry-picking or resetting back to it).
Conflicts occur when Git cannot automatically merge changes because the same lines in the same file were modified on diverging branches.
Resolving a Conflict:
Git will pause the merge/rebase and mark the conflicting files.
Open the file(s). You will see conflict markers:
<<<<<<< HEAD (Your changes)
// Code from your current branch
=======
// Code from the branch you are merging/rebasing from
>>>>>>> <branch_name_or_hash>
Manually edit the file to resolve the differences and remove the conflict markers.
For a merge: git add <resolved_file>
and then git commit
.
For a rebase: git add <resolved_file>
and then git rebase --continue
.
ours
vs. theirs
:
ours
is your current branch; theirs
is the branch being merged in.ours
refers to the target branch (e.g., main
), and theirs
refers to the commits from your feature branch being replayed.git stash
: A temporary clipboard for uncommitted changes. git stash
saves your working directory and staging area changes, git stash pop
reapplies them. It works like a stack (Last-In, First-Out).
Squashing (git rebase -i
): Combining multiple commits into a single commit. This is done with an interactive rebase (-i
). You mark commits with pick
(keep) or s
(squash into previous).
git cherry-pick <commit>
: Applies a single commit from another branch onto your current branch.
git bisect
: A powerful debugging tool that uses a binary search to find the exact commit that introduced a bug. You start it with git bisect start
, mark a known good
commit and a known bad
commit, and Git will check out commits in between, asking you to mark each as good
or bad
until it isolates the culprit.
git worktree
: Allows you to have multiple branches checked out in different directories at the same time, avoiding the need to constantly switch branches or stash changes.
git tag
: Creates an immutable (unchangeable) pointer to a specific commit, typically used for versioning releases (e.g., git tag -a v1.0.0 -m "Version 1.0.0"
).
git status
-> git add
-> git commit
.git reset
(local), git revert
(public), and git reflog
(recovery) are essential for fixing mistakes.upstream
to keep your fork in sync.stash
, squash
, and cherry-pick
help maintain a clean and understandable commit history.git bisect
is an incredibly efficient way to find the origin of a bug.Enjoyed the article? I write about 1-2 a month. Subscribe via email or RSS feed.