Git
Git is the industry-standard distributed version control system, essential for tracking code changes and enabling seamless collaboration. This tutorial covers everything from initial setup to advanced collaboration workflows.
Introduction and Core Concepts
What is Git?
Git is a distributed version control system that tracks changes in your code over time. Unlike centralized systems, every developer has a complete copy of the repository history on their local machine. This distributed nature makes Git fast, reliable, and resilient.
Key benefits:
- Version Control: Save snapshots of your work and revert to previous versions if needed
- Collaboration: Multiple people can work on the same project without conflicts
- Experimentation: Try new features on branches without affecting the main codebase
- Backup: Your entire project history is saved locally and can be synced to remote hosts
Git vs GitHub
- Git: The version control software that runs on your computer
- GitHub: A cloud-based hosting service for Git repositories, providing collaboration tools like pull requests and issue tracking
Installation and Setup
Installing Git
Windows:
# Download from https://git-scm.com/download/win
# Or use package manager
winget install Git.GitMac:
# Using Homebrew
brew install git
# Or download from git-scm.comLinux (Ubuntu/Debian):
sudo apt update
sudo apt install gitInitial Configuration
Configure your identity and preferences:
# Set your name and email (used in commits)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# Set default branch name
git config --global init.defaultBranch main
# Set default editor
git config --global core.editor "code --wait" # VS Code
# Or use: nano, vim, etc.
# Verify configuration
git config --listThe --global flag applies these settings to all repositories on your computer.
Basic Workflow
The Three-Stage Architecture
Git uses three main states for your files:
- Working Directory: Your files as you edit them
- Staging Area (Index): Files you’ve marked to be committed
- Repository (Local Database): Committed snapshots
Initialize a Repository
# Create a new directory and navigate into it
mkdir my-project
cd my-project
# Initialize Git repository
git initThis creates a hidden .git folder that stores all version control data.
Core Commands
Check Repository Status
git statusShows which files are modified, staged, or untracked.
Stage Changes
# Add a specific file
git add filename.py
# Add all files in current directory
git add .
# Add all .py files
git add *.pyCommit Changes
# Commit with a message
git commit -m "Add README file"
# Add and commit in one step (only for tracked files)
git commit -am "Update existing files"Good commit messages are concise (under 50 characters for the first line) and use the imperative mood (“Add feature”, not “Added feature”).
Viewing History and Changes
View Commit History
# Full history
git log
# One line per commit
git log --oneline
# With graph visualization
git log --graph --oneline --all
# Last 5 commits
git log -5
# Search commits by message
git log --grep="bug fix"View Differences
# Changes in working directory (unstaged)
git diff
# Changes in staging area
git diff --staged
# Changes in a specific file
git diff filename.py
# Changes between commits
git diff commit1 commit2Undoing and Fixing Mistakes
Discard Uncommitted Changes
# Discard changes in working directory
git restore filename.py
# Discard all unstaged changes
git restore .
# Unstage a file (keep changes)
git restore --staged filename.pyWarning: git restore permanently discards uncommitted changes.
Remove Files
# Remove from Git and filesystem
git rm filename.py
# Remove from Git only (keep local file)
git rm --cached filename.py
# Remove directory
git rm -r directory/Revert or Reset Commits
Revert (safe for public commits):
# Creates a new commit that undoes the changes
git revert commit-hashReset (use with caution):
# Undo last commit but keep changes staged
git reset --soft HEAD^
# Undo last commit and discard changes
git reset --hard HEAD^Amend the last commit:
# Change the last commit message
git commit --amend -m "New commit message"Branching
What are Branches?
Branches are parallel versions of your code. They allow you to work on features without affecting the main codebase, experiment safely, and collaborate without conflicts.
Working with Branches
# List local branches
git branch
# List all branches (local + remote)
git branch -a
# Create a new branch
git branch feature-name
# Create and switch to branch
git checkout -b feature-name
# OR (modern syntax)
git switch -c feature-name
# Switch to existing branch
git switch branch-nameMerging Branches
# Switch to target branch (e.g., main)
git switch main
# Merge feature branch into current branch
git merge feature-nameHandling Merge Conflicts
When Git can’t automatically merge changes, conflict markers appear in files:
<<<<<<< HEAD
This line was changed in the current branch
=======
And was also changed on the other branch
>>>>>>> branch-to-mergeTo resolve:
- Edit the file to choose which changes to keep (or combine them)
- Stage the resolved file:
git add filename - Commit the merge:
git commit
Delete Branches
# Delete local branch (safe, won't delete unmerged changes)
git branch -d branch-name
# Force delete (even if not merged)
git branch -D branch-nameRemote Repositories (GitHub)
Add a Remote
# Add remote (usually done once)
git remote add origin https://github.com/username/repo.git
# View remotes
git remote -vorigin is the default name for your main remote.
Clone a Repository
# Clone via HTTPS
git clone https://github.com/username/repo.git
# Clone via SSH
git clone git@github.com:username/repo.git
# Clone specific branch
git clone -b branch-name https://github.com/username/repo.gitPush and Pull
# Push local commits to remote
git push origin main
# Pull changes from remote (fetch + merge)
git pull origin main
# First push (sets upstream)
git push -u origin mainCollaborate with Forks
Update your fork from the original repository:
# Add original repo as "upstream"
git remote add upstream https://github.com/original-owner/repo.git
# Fetch and merge upstream changes
git fetch upstream
git checkout main
git merge upstream/main
git push origin mainAdvanced Techniques
Stashing Changes
Temporarily save uncommitted work to switch branches:
# Save changes temporarily
git stash
# List stashes
git stash list
# Apply most recent stash
git stash apply
# Apply and remove most recent stash
git stash pop
# Remove most recent stash
git stash dropInteractive Rebase
Squash, reorder, or edit commits:
# Rebase last 3 commits interactively
git rebase -i HEAD~3Cherry-Picking
Apply a specific commit to the current branch:
git cherry-pick commit-hashTagging
Mark specific points in history (e.g., releases):
# Create a lightweight tag
git tag v1.0
# Create an annotated tag
git tag -a v1.0 -m "Version 1.0"
# Push tags to remote
git push origin --tags.gitignore
Prevent Git from tracking unnecessary files (e.g., node_modules, .env, IDE files).
Example .gitignore:
# General
.DS_Store
# Editors
.idea
.vscode
# Project
.env
node_modules/
# Wildcard to ignore all .log files
*.logBest Practices
Commit Messages
- Write clear, concise commit messages in the imperative mood
- First line should be 50 characters or less
- Provide a detailed body if necessary, separated by a blank line
Workflow Tips
- Commit often, push regularly
- Pull before you push to avoid conflicts
- Use branches for features and bug fixes
- Use .gitignore to exclude unnecessary files
- Check status frequently (
git status) to understand your current state
Common Mistakes to Avoid
“fatal: refusing to merge unrelated histories”
git pull origin main --allow-unrelated-histories“error: failed to push some refs”
git pull origin main # Pull changes firstAuthentication failures on GitHub: Use a Personal Access Token (PAT) instead of a password.