๐ก What is Git?Git is a distributed version control system. Every developer has a full copy of the entire repository history on their machine โ no single point of failure.
git initInitialize
Create a new Git repository in the current directory. This creates a hidden .git folder that stores all version history.
$git init # init in current directory
$git init my-project # init in new folder
Initialized empty Git repository in /home/user/project/.git/
git cloneInitialize
Download a repository from a remote URL (GitHub, GitLab, etc.) including all its history.
$git clone <url>
$git clone <url> my-folder # clone into custom folder
$git clone --depth 1 <url> # shallow clone
Cloning into 'project'...
remote: Enumerating objects: 142, done.
Receiving objects: 100% (142/142), 2.1 MiB | 4.2 MiB/s, done.
git statusInspect
Show the state of the working directory and staging area. The most-used command โ run it constantly.
$git status
$git status -s # short format
On branch main
Changes to be committed:
new file: src/auth.js
Changes not staged for commit:
modified: README.md
Untracked files:
.env
โ ๏ธ The three statesEvery file in Git lives in one of three states: modified (changed but not staged), staged (marked for next commit), or committed (safely stored in the database).
git configSetup
Get and set repository or global options. Always set your name and email before your first commit.
$git config --global user.name "Your Name"
$git config --global user.email "you@example.com"
$git config --global core.editor vim
$git config --list # view all settings
--globalApply to all repos for the current user (~/.gitconfig)
--localApply only to the current repository (.git/config)
--systemApply system-wide for all users
--listShow all configuration values
๐ก Useful aliasesSpeed up your workflow with aliases:
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.lg "log --oneline --graph --all"
git addStage
Add file contents to the staging area (index). You choose exactly what goes into the next commit.
$git add file.txt
$git add . # stage all changes
$git add src/ # stage entire directory
$git add -p # interactively stage hunks
-p / --patchInteractively choose which hunks to stage (powerful)
-A / --allStage all changes including deletions
-uStage modifications and deletions, not new files
git commitCommit
Record staged changes as a new commit in the repository history. Each commit is permanent and addressable by its SHA hash.
$git commit -m "feat: add user authentication"
$git commit -am "fix: correct typo" # stage tracked + commit
$git commit --amend # modify the last commit
[main 3f9a2b1] feat: add user authentication
3 files changed, 48 insertions(+), 2 deletions(-)
create mode 100644 src/auth.js
-m "msg"Commit with inline message (skip editor)
-aAuto-stage tracked modified files before commit
--amendRewrite the last commit (message or files)
--no-editAmend without changing the commit message
๐ก Good commit messagesUse the imperative mood: "Add feature" not "Added feature". Format: type: short description โ types: feat, fix, docs, style, refactor, test, chore.
git logHistory
Show the commit history. Without options it's verbose โ combine flags to get exactly what you need.
$git log
$git log --oneline
$git log --oneline --graph --all
$git log --author="Name" --since="2 weeks ago"
$git log -p file.txt # history of a file
d71e4a9 (HEAD -> main) feat: add dashboard
a3f9b2c fix: resolve login redirect loop
7c8d1e2 (origin/main) docs: update README
f9b3c4a chore: initial commit
--onelineOne commit per line (hash + message)
--graphASCII branch graph alongside commits
--allShow all branches, not just current
-pShow patch (diff) for each commit
-n <num>Limit to last n commits
--since / --untilFilter by date range
git diffInspect
Show changes between the working directory, staging area, and commits.
$git diff # unstaged changes
$git diff --staged # staged vs last commit
$git diff main..feature # between branches
$git diff HEAD~1 HEAD # last commit changes
diff --git a/src/app.js b/src/app.js
@@ -14,6 +14,8 @@ const app = express();
- app.use(cors())
+ app.use(cors({ origin: process.env.CLIENT_URL }))
+ app.use(helmet())
git branchBranch
List, create, rename, or delete branches.
$git branch # list local branches
$git branch feature/auth # create branch
$git branch -d feature/auth # delete (safe)
$git branch -D feature/auth # force delete
$git branch -a # list all including remote
git checkout / git switchNavigate
Switch between branches. git switch is the modern replacement for the branch-switching use of checkout.
$git checkout feature/auth
$git checkout -b feature/auth # create + switch
$git switch feature/auth # modern way
$git switch -c feature/auth # create + switch (modern)
๐ก Branch namingUse prefixes that communicate intent: feature/, fix/, hotfix/, release/, chore/. Keep names short and lowercase with hyphens.
git mergeIntegrate
Join two branches together. First, checkout the branch you want to merge INTO, then run merge.
$git checkout main
$git merge feature/auth
$git merge --no-ff feature/auth # always make merge commit
$git merge --squash feature/auth # squash to one commit
$git merge --abort # cancel a conflicted merge
Updating a3f9b2c..d71e4a9
Fast-forward
src/auth.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
โก Conflict resolutionWhen Git can't auto-merge, it marks conflict regions in the file with <<<<<<<, =======, >>>>>>>. Edit the file to keep what you want, then git add the file and git commit.
git rebaseIntegrate
Move or combine commits onto a different base commit. Used to keep a feature branch up-to-date with main.
$git rebase main # rebase current branch onto main
$git rebase -i HEAD~3 # interactive: reorder/squash/edit
$git rebase --continue # after resolving conflict
$git rebase --abort # cancel rebase
-i / --interactiveChoose pick, squash, reword, drop for each commit
--onto <base>Rebase onto a specific commit or branch
๐จ Golden RuleNever rebase commits that have been pushed to a shared remote branch. You will rewrite history others have based work on, causing serious conflicts.
git remoteRemote
Manage connections to remote repositories.
$git remote -v
$git remote add origin https://github.com/user/repo.git
$git remote remove origin
$git remote rename origin upstream
git push / git pull / git fetchSync
Transfer commits between local and remote repositories.
$git push origin main
$git push -u origin feature/auth # set upstream
$git push --force-with-lease # safe force push
$git pull # fetch + merge
$git pull --rebase # fetch + rebase (cleaner)
$git fetch --all # download without merging
๐ก fetch vs pullgit fetch downloads remote changes without touching your working tree. git pull = fetch + merge. Prefer fetch when you want to review before integrating.
git resetUndo
Move HEAD (and optionally the index/working tree) backwards to a previous commit. Rewrites history โ only use on local, unpushed commits.
$git reset --soft HEAD~1 # undo commit, keep staged
$git reset --mixed HEAD~1 # undo + unstage (default)
$git reset --hard HEAD~1 # undo + discard changes
๐จ --hard is destructivegit reset --hard discards uncommitted changes permanently. Use with caution. If you need to undo a pushed commit, use git revert instead.
git revertUndo
Create a new commit that undoes the changes from a previous commit. Safe to use on shared branches โ it doesn't rewrite history.
$git revert HEAD # undo last commit
$git revert a3f9b2c # undo specific commit
$git revert --no-commit HEAD # stage revert without committing
git restoreUndo
Discard working directory changes or unstage files. The modern replacement for the restore-file use of git checkout.
$git restore file.txt # discard working dir changes
$git restore --staged file.txt # unstage file
git stashShelve
Save and restore incomplete work on a stack.
$git stash # stash current changes
$git stash -m "WIP: half-done feature"
$git stash list # view all stashes
$git stash pop # apply + drop latest stash
$git stash apply stash@{2} # apply specific stash
$git stash drop stash@{0}
git cherry-pickAdvanced
Apply a specific commit from another branch onto the current branch.
$git cherry-pick a3f9b2c
$git cherry-pick a3f9b2c..d71e4a9 # range
git bisectDebug
Binary search through commits to find the one that introduced a bug.
$git bisect start
$git bisect bad # mark current commit as bad
$git bisect good v1.0.0 # mark known good commit
$git bisect reset # return to HEAD
git reflogRecovery
Show a log of where HEAD has been. Your safety net โ recover lost commits after a bad reset.
$git reflog
$git checkout HEAD@{3} # go back to state 3 actions ago
๐ GitHub Flow (recommended for most teams)
One long-lived branch (main). Every change goes through a short-lived feature branch + pull request. Deploy from main after merge. Simple and effective.
๐ Git Flow (for versioned releases)
main + develop + feature/* + release/* + hotfix/*. More rigid, suits teams shipping versioned software. Overhead increases with team size.
๐ Trunk-Based Development
Everyone commits to main (trunk) frequently โ multiple times per day. Feature flags control what's visible to users. Requires strong CI/CD. Used by large orgs like Google.
Ready to try these patterns? Open the playground โ