A helpful manual for navigating the Git world β a compilation of the most common Git commands with clear explanations. Whether you're a total beginner or need a quick refresher, this guide has you covered. Cheers to coding! π
- Getting Started
- The Complete Workflow
- Mastering Branches
- Merge Strategies & Conflict Resolution
- Remote Repository Mastery
- Time Travel: Undoing & Fixing
- Investigation & Information
- Stashing & Temporary Storage
- Advanced Git Techniques
- Configuration & Customization
- Emergency Git Commands
- Pro Tips & Best Practices
Make sure Git is installed on your machine:
# Check if Git is installed
git --version
# Output: git version 2.x.xπ‘ Beginner Tip: If you get "command not found", download Git from git-scm.com
# Initialize a new repository
git init
# This creates a hidden .git folder β the magic happens here!# Check what's happening (always a good idea!)
git status
# Output: On branch master (or main)
# No commits yet
# nothing to commitβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GIT WORKFLOW β
β β
β Working Dir Staging Area Local Repo Remote β
β (your files) (git add) (git commit) (GitHub) β
β β
β [Edit files] ββgit addβββΊ [Staged] ββgit commitβββΊ β
β [Committed] β
β β β
β [Updated] βββgit pullββ git pushβββΊ β
β [Remote Repo (origin)] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Start your local repository
git init
# Add your remote repository (where your code will live online)
git remote add origin https://github.com/username/your-repo.git
# Check your remote is set up correctly
git remote -v
# origin https://github.com/username/your-repo.git (fetch)
# origin https://github.com/username/your-repo.git (push)# If you're on 'master' and want to switch to 'main'
git branch -M main
# This renames your current branch to 'main'
# Or create main branch if it doesn't exist
git checkout -b mainπ‘ Beginner Tip: Modern Git uses
mainas the default branch name. If you seemaster, you can rename it!
# Create your first file
echo "# My Awesome Project" > README.md
# Add file to staging area
git add README.md
# Or add everything at once
git add .
# Make your first commit
git commit -m "Initial commit: Added README file"# Push and set upstream branch
git push -u origin main
# The -u flag sets main as the default tracking branch (only needed once!)# If remote repository already has content, pull it first
git pull origin main
# If you get "fatal: refusing to merge unrelated histories"
git pull origin main --allow-unrelated-histories
# This merges two separate Git histories β very common when starting!π‘ Why branches? Think of branches as parallel universes for your code. You can experiment on a feature branch without breaking the main codebase.
# See all branches (local + remote)
git branch -a
# * main (current branch marked with *)
# remotes/origin/main
# Create a new branch
git branch feature/awesome-feature
# Switch to branch (classic way)
git checkout feature/awesome-feature
# Switch to branch (modern way β Git 2.23+)
git switch feature/awesome-feature
# Create AND switch in one command (most common)
git checkout -b feature/new-feature
# or
git switch -c feature/new-feature# Rename current branch
git branch -m new-branch-name
# Rename any branch
git branch -m old-name new-name
# Copy a branch
git checkout -b new-branch existing-branch
# Delete local branch (safe β only deletes if merged)
git branch -d feature/completed-feature
# Force delete local branch
git branch -D feature/unwanted-feature
β οΈ WARNING:git branch -Dis destructive β any unmerged work on that branch will be lost!
# Delete remote branch
git push origin --delete feature/old-feature# Set upstream for current branch
git branch --set-upstream-to=origin/main
# Push new branch and set upstream
git push -u origin feature/my-feature
# See tracking relationships for all local branches
git branch -vv
# main a1b2c3d [origin/main] My last commit message# Switch to target branch (usually main)
git checkout main
# Merge feature branch into current branch
git merge feature/awesome-feature
# Delete merged branch (clean up!)
git branch -d feature/awesome-feature# When merging, automatically accept their changes for conflicts
git merge feature/other-branch -X theirs
# Or during pull
git pull origin main -X theirs# When merging, prefer your local changes
git merge feature/other-branch -X ours
# During pull
git pull origin main -X oursgit merge --no-ff feature/awesome-feature
# Always creates a merge commit, preserving branch historyBefore: main: ββAββB
\
feature: ββCββDββEββF
After (--no-ff):
main: ββAββBββββββββββββββββM β Merge commit
\ /
feature: ββCββDββEββF
π‘ Note:
--no-ffkeeps all individual feature branch commits and adds a new merge commit. Merging a Pull Request on GitHub is essentially a remotegit merge --no-ff.
git merge --squash feature/many-commits
git commit -m "Add awesome feature"
# Combines all commits from feature branch into ONE commitBefore: main: ββAββB
\
feature: ββCββDββEββF
After (--squash):
main: ββAββBββS β Single squash commit (C+D+E+F combined)
π‘ When to use:
--squashis great when your feature branch has messy "WIP" commits you don't want in history.
# After a failed merge, see which files have conflicts
git status
# List only conflicted files
git diff --name-only --diff-filter=U# Open conflicted file β you'll see conflict markers:
# <<<<<<< HEAD
# Your changes here
# =======
# Their changes here
# >>>>>>> branch-name
# 1. Edit the file to keep what you want
# 2. Remove ALL conflict markers (<<<, ===, >>>)
# 3. Stage the resolved file
git add conflicted-file.txt
# 4. Complete the merge
git commit -m "Merge: resolved conflict in conflicted-file.txt"# Accept ALL their changes (entire repo)
git checkout --theirs .
git add .
git commit
# Accept ALL your changes (entire repo)
git checkout --ours .
git add .
git commit
# Open a visual merge tool
git mergetoolgit merge --abort
# Cancels the merge and returns to the state before you started# Add multiple remotes
git remote add upstream https://github.com/original/repo.git
git remote add fork https://github.com/yourusername/repo.git
# List all remotes
git remote -v
# Remove a remote
git remote remove upstream# Change origin to point to new repository
git remote set-url origin https://github.com/new-username/new-repo.git
# Verify the change
git remote -v
# Test the connection
git remote show origingit remote remove origin
git remote add origin https://github.com/new-username/new-repo.git
git push -u origin main# Switch from HTTPS to SSH
git remote set-url origin git@github.com:username/repo.git
# Switch from SSH to HTTPS
git remote set-url origin https://github.com/username/repo.git| Scenario | Command |
|---|---|
| Transferred repo ownership | git remote set-url origin https://github.com/user2/repo.git |
| Forked a repo | git remote set-url origin https://github.com/yourusername/fork.git |
| Company moved to GitLab | git remote set-url origin https://gitlab.com/company/project.git |
| New local repo to new remote | git remote add origin <url> β git push -u origin main |
# Fetch all branches from all remotes (doesn't change your files)
git fetch --all
# Fetch specific remote
git fetch origin
# Fetch and prune deleted remote branches
git fetch --prune
# Keeps your local remote-tracking list in sync
# Pull with rebase (cleaner, linear history)
git pull --rebase origin main
# Pull a specific branch
git pull origin feature/specific-branchπ‘ Tip:
git fetchis always safe β it downloads info but never changes your working files.git pull=git fetch+ merge (or rebase), depending on your configuration/flags.
# Push all local branches
git push --all origin
# Push tags
git push --tags
β οΈ WARNING: Force push can destroy others' work on shared branches!
# Force push (overwrites remote history β dangerous!)
git push --force origin main
# Safer force push β fails if someone else pushed since your last pull
git push --force-with-lease origin main
# Push new branch and set upstream
git push -u origin feature/new-branch
# Push to a differently-named remote branch
git push origin local-branch:remote-branch
# e.g. git push origin develop:staging# Discard changes in a specific file
git checkout -- filename.txt
# or (newer syntax)
git restore filename.txt
# Discard ALL changes in working directory
git checkout -- .
git restore .π‘ Note: These commands do NOT affect untracked files (files Git doesn't know about yet).
# Remove untracked files (preview first!)
git clean -n # Dry run β shows what WOULD be deleted
git clean -f # Remove untracked files
git clean -fd # Remove untracked files AND directories
# Untrack a specific file (keeps it on disk, removes from Git)
git rm --cached <file>
# e.g. git rm --cached app/google-services.json
β οΈ WARNING:git clean -fis permanent! Always rungit clean -nfirst to preview.
# Unstage a specific file (undo git add)
git reset HEAD filename.txt
# or (newer syntax)
git restore --staged filename.txt
# Unstage ALL files
git reset HEAD
git restore --staged .RESET MODES AT A GLANCE:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
--soft Undo commit β
Keep in staging β
Keep files
--mixed Undo commit β Remove from stage β
Keep files (DEFAULT)
--hard Undo commit β Remove from stage β LOSE files
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Undo last commit, keep changes staged and ready to re-commit
git reset --soft HEAD~1
# Undo multiple commits
git reset --soft HEAD~3# Undo last commit, keep changes in working directory (unstaged)
git reset HEAD~1
# Reset to specific commit
git reset abc1234# DANGER: Permanently loses ALL uncommitted changes
git reset --hard HEAD~1
# Reset to specific commit (lose everything after it)
git reset --hard abc1234
# Reset to match remote state exactly
git reset --hard origin/main
β οΈ DANGER:git reset --hardis irreversible for uncommitted changes. Only use it if you're 100% sure!
# Create a new commit that reverses the last commit
git revert HEAD
# Revert a specific commit
git revert abc1234
# Revert a merge commit
git revert -m 1 merge-commit-hashπ‘
revertvsreset: Usegit reverton shared/public branches β it adds a new "undo" commit without rewriting history. Usegit resetonly on your own local commits that haven't been pushed.
# Full commit log
git log
# Compact one-line-per-commit view (most useful!)
git log --oneline
# Last 5 commits, one line each
git log --oneline -5
# Visual branch graph
git log --oneline --graph --all
# Shows a visual tree of all branches and merges
# Log with stats (which files changed, how many lines)
git log --stat
# Search commits by author
git log --author="John"
# Search commits by message keyword
git log --grep="fix bug"
# Show commits in a date range
git log --after="2024-01-01" --before="2024-06-01"
# Show what changed in each commit
git log -p# Show unstaged changes (what you changed but haven't git added)
git diff
# Show staged changes (what you've git added but not committed)
git diff --staged
# also works: git diff --cached
# Show changes between two commits
git diff abc1234 def5678
# Show changes between two branches
git diff main..feature/my-feature
# Show only filenames that changed (not the full diff)
git diff --name-only# Show what a specific commit changed
git show abc1234
# Show a specific file at a specific commit
git show abc1234:path/to/file.txt
# Show the latest commit on current branch
git show HEAD# Show who last modified each line of a file
git blame filename.txt
# Output: abc1234 (John Doe 2024-05-01) line content here
# Blame with email addresses
git blame -e filename.txt
# Blame a specific range of lines (lines 10β30)
git blame -L 10,30 filename.txtπ‘ Use case: When you find a bug and want to know who wrote that line and why (check the commit message!).
# Show commit count per author
git shortlog -sn
# Full shortlog with commit messages
git shortlog
# Count total commits in repo
git rev-list --count HEADπ‘ What is stashing? Like putting your unfinished work in a drawer so you can quickly switch tasks β then come back and pick up right where you left off.
# Stash your current changes (staged + unstaged)
git stash
# Your working directory is now clean!
# Stash with a descriptive message
git stash push -m "WIP: half-done login feature"
# List all your stashes
git stash list
# stash@{0}: WIP: half-done login feature
# stash@{1}: On main: experimental changes
# Apply the most recent stash (keeps it in the stash list)
git stash apply
# Apply AND remove from stash list
git stash pop# Apply a specific stash by index
git stash apply stash@{2}
# Show what's in a stash before applying
git stash show stash@{0}
git stash show -p stash@{0} # Full diff
# Drop (delete) a specific stash
git stash drop stash@{1}
# Clear ALL stashes (careful!)
git stash clear
β οΈ WARNING:git stash clearpermanently deletes all stashes.
# Stash only unstaged changes (keep staged changes)
git stash --keep-index
# Also stash untracked files
git stash -u
# or
git stash --include-untracked
# Create a branch from a stash (useful when stash conflicts with current code)
git stash branch feature/from-stash stash@{0}1. You're working on feature X...
git stash push -m "WIP: feature X"
2. Switch to fix an urgent bug on main:
git checkout main
# fix bug, commit
3. Come back to your feature:
git checkout feature/x
git stash pop β Your work is back!
π‘ Rebase vs Merge: Rebase creates a cleaner, linear history. Merge preserves the true branch structure. Neither is wrong β it depends on your team's preference.
# Rebase current branch onto main
git rebase main
# "Replays" your commits on top of main's latest commitBefore rebase:
main: ββAββBββC
\
feature: ββDββE
After: git rebase main (while on feature)
main: ββAββBββC
\
feature: ββD'ββE' β New commits (replayed on top of C)
# Interactive rebase β edit, squash, reorder last 3 commits
git rebase -i HEAD~3
# Opens editor where you can:
# pick β keep commit
# squash β merge into previous commit
# reword β change commit message
# drop β delete commit entirely
# Abort rebase if something goes wrong
git rebase --abort
# Continue rebase after resolving conflicts
git rebase --continue
β οΈ WARNING: Never rebase commits that have already been pushed to a shared branch β it rewrites history and causes problems for teammates.
# Apply a specific commit from another branch to current branch
git cherry-pick abc1234
# Makes a copy of that commit on your current branch
# Cherry-pick multiple commits
git cherry-pick abc1234 def5678
# Cherry-pick a range of commits
git cherry-pick abc1234^..def5678
# Cherry-pick without auto-committing (stage changes only)
git cherry-pick --no-commit abc1234π‘ Use case: You merged a bug fix to your feature branch, but want to also apply JUST that fix to main without merging the whole feature.
# Start a binary search through your commit history
git bisect start
# Mark the current state as bad (bug exists here)
git bisect bad
# Mark a known-good commit (when bug didn't exist)
git bisect good abc1234
# Git will checkout commits in between β test each one:
# If bug exists: git bisect bad
# If bug is gone: git bisect good
# Git narrows it down automatically!
# When finished, reset back to normal
git bisect resetπ‘ Use case: "My app broke sometime in the last 200 commits β which one introduced the bug?" Bisect finds it in ~8 steps instead of 200!
# Create a lightweight tag
git tag v1.0.0
# Create an annotated tag (with message β recommended for releases)
git tag -a v1.0.0 -m "Version 1.0.0 β First stable release"
# Tag a specific commit
git tag -a v0.9.0 abc1234 -m "Beta release"
# List all tags
git tag
# Show tag details
git show v1.0.0
# Push a specific tag to remote
git push origin v1.0.0
# Push ALL tags to remote
git push --tags
# Delete a local tag
git tag -d v1.0.0
# Delete a remote tag
git push origin --delete v1.0.0# Set your name (appears in commit history)
git config --global user.name "Your Name"
# Set your email (should match your GitHub email)
git config --global user.email "you@example.com"
# Set default branch name to 'main' for new repos
git config --global init.defaultBranch main
# Set preferred editor for commit messages
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "nano" # Nano
git config --global core.editor "vim" # Vim# See all your global config settings
git config --global --list
# See local repo config (overrides global)
git config --local --list
# Check a specific setting
git config user.name
# See where a setting comes from
git config --show-origin user.name# Windows: auto-convert line endings
git config --global core.autocrlf true
# Mac/Linux: don't convert
git config --global core.autocrlf input
# Fix long file path issues on Windows
git config --system core.longpaths true# Create shortcuts for common commands
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm "commit -m"
git config --global alias.last "log -1 HEAD"
# Now you can type:
git st # = git status
git co main # = git checkout main
git last # = show last commit
# Fancy log alias
git config --global alias.lg "log --oneline --graph --all --decorate"# Speed up large repositories
git config --global core.preloadindex true
git config --global core.fscache true
# Auto-setup remote tracking when pushing new branches
git config --global push.autoSetupRemote true
# Use 'main' as default branch for new repos
git config --global init.defaultBranch main
# Always use rebase instead of merge on pull
git config --global pull.rebase trueπ‘ Reflog is a superpower. Git records every movement of HEAD (even through resets and branch deletions) for ~90 days. You can recover almost anything!
# See a log of every action Git has taken
git reflog
# HEAD@{0}: reset: moving to HEAD~1
# HEAD@{1}: commit: Add login page
# HEAD@{2}: commit: Fix navbar bug
# HEAD@{3}: checkout: moving from feature to main
# Recover a commit you accidentally reset away
git reflog
# Find the SHA of the commit you want (e.g. abc1234)
git reset --hard abc1234
# OR create a new branch at that commit:
git checkout -b recovery-branch abc1234# Find the lost commit SHA in reflog
git reflog | grep "the thing you remember"
# Restore it to a new branch
git checkout -b rescued-branch abc1234
# Or apply it with cherry-pick
git cherry-pick abc1234# "Detached HEAD" means you're not on any branch
# This happens when you checkout a specific commit:
git checkout abc1234
# WARNING: You are in 'detached HEAD' state
# To save any work you do here, create a branch:
git checkout -b my-new-branch
# Or just go back to a branch
git checkout main# Find the last commit SHA that was on the deleted branch
git reflog
# Recreate the branch at that commit
git checkout -b recovered-branch abc1234# Fix the most recent commit message (before pushing!)
git commit --amend -m "Corrected commit message"
# Add a forgotten file to your last commit
git add forgotten-file.txt
git commit --amend --no-edit # Keeps existing message
β οΈ WARNING:git commit --amendrewrites history. Only use it on commits that haven't been pushed yet!
# Something went terribly wrong β reset to exactly match remote
git fetch origin
git reset --hard origin/main
git clean -fd
# Find ALL unreachable objects (dangling commits, blobs)
git fsck --lost-found# Great commit message format:
# type: Brief description (50 chars max)
#
# More detailed explanation if needed (wrap at 72 chars)
#
# - Use bullet points for multiple changes
# - Reference issues: Fixes #123
# Example:
git commit -m "feat: Add user authentication system
- Implement JWT token handling
- Add login/logout endpoints
- Create user registration flow
Fixes #42"| Type | Emoji | When to Use |
|---|---|---|
feat |
β¨ | New feature |
fix |
π | Bug fix |
docs |
π | Documentation only |
style |
π¨ | Formatting, no code change |
refactor |
β»οΈ | Code restructuring |
perf |
β‘ | Performance improvement |
test |
β | Adding/fixing tests |
chore |
π§ | Maintenance, build tasks |
main # Production-ready code only
develop # Integration branch β ongoing work
feature/* # New features (branch from develop)
release/* # Release preparation
hotfix/* # Emergency production fixes
1. Branch from main
2. Make changes and commit
3. Open a pull request
4. Get code review
5. Merge to main
6. Delete branch
# Always check before doing anything destructive
git status
git log --oneline -5
# Do a dry run before cleaning
git clean --dry-run
# Backup important branches before risky operations
git branch backup-main main
# Always prefer --force-with-lease over --force
git push --force-with-lease origin main# Logs and temp files
*.log
*.tmp
# Environment files (never commit secrets!)
.env
.env.local
.env.production
# OS files
.DS_Store
Thumbs.db
# Dependencies
node_modules/
vendor/
# Build output
dist/
build/
*.class
*.o
# IDEs
.idea/
.vscode/
*.swp
# Ignore everything except specific files
*
!.gitignore
!src/
!src/**
# Keep empty directories tracked
logs/.gitkeep# Hooks live in .git/hooks/
# Example: pre-commit hook (runs before every commit)
#!/bin/sh
npm test
if [ $? -ne 0 ]; then
echo "β Tests failed! Commit aborted."
exit 1
fi
echo "β
Tests passed. Committing..."
# Make hook executable
chmod +x .git/hooks/pre-commitYou've explored the complete Git universe! π From git init to emergency recovery, you now have the tools to handle any Git situation confidently.
| Task | Command |
|---|---|
| Check status | git status |
| Stage all changes | git add . |
| Commit | git commit -m "message" |
| Push | git push |
| Pull updates | git pull |
| Create & switch branch | git checkout -b feature/name |
| Merge a branch | git merge feature/name |
| Delete branch | git branch -d feature/name |
| Stash work | git stash |
| Restore stash | git stash pop |
| Undo last commit (keep files) | git reset --soft HEAD~1 |
| Undo last commit (lose files) | git reset --hard HEAD~1 |
| Safe undo (public repos) | git revert HEAD |
| Find lost commits | git reflog |
| See who changed a line | git blame filename |
| Visual commit graph | git log --oneline --graph --all |
- Commit early, commit often π
- Write descriptive commit messages π¬
- Always pull before push β¬οΈβ¬οΈ
- Use branches for every feature πΏ
- Test before you commit β
- Never force push to shared branches π‘οΈ
- Use
--force-with-leaseinstead of--forceβ οΈ - When in doubt,
git reflogcan save you π¨
Happy Git-ing! May your merges be conflict-free and your commits be meaningful! πβ¨
"With great Git power comes great Git responsibility!" β Uncle Git π·οΈ
- Official Git Documentation
- Pro Git Book (Free)
- Interactive Git Learning
- Git Cheat Sheet
- Conventional Commits Spec
β This file is a living document. Happy coding! π
Made with β€οΈ for developers who want to Git things done right!