Git is a distributed version control system (DVCS) that helps developers track changes in their codebase. Created by Linus Torvalds in 2005, Git allows:
- Tracking every modification to files
- Collaborating with other developers
- Reverting to previous versions when needed
- Managing multiple parallel development streams
- Version History: Never lose previous work
- Team Collaboration: Multiple people can work simultaneously
- Branching: Isolate features/bug fixes without affecting main code
- Open Source: Free and widely adopted (used by >90% of developers)
- Git: The version control software that runs locally
- GitHub/GitLab/Bitbucket: Cloud platforms that host Git repositories with additional features
Download Git from git-scm.com and verify:
Windows/macOS:
- Download and run the installer
Linux (Debian/Ubuntu):
sudo apt update && sudo apt install git -yLinux (RHEL/CentOS):
sudo yum install git -yVerify installation:
git --version # Should show e.g., "git version 2.39.2"Set your identity (used in commits):
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"Optional settings:
git config --global core.editor "code --wait" # Use VS Code as default editor
git config --global init.defaultBranch "main" # Set default branch nameView your Git config:
git config --listInitialize a new repository:
mkdir my-project
cd my-project
git init # Creates a hidden .git directoryCheck repository status:
git status-
Create a new file:
touch README.md
-
Add content:
echo "# My Project" >> README.md
-
Check status:
git status # Shows README.md as "untracked" -
Stage the file:
git add README.md
-
Commit changes:
git commit -m "Add project README" -
View commit history:
git log # Shows commit history with details git log --oneline # Compact view
-
Create multiple files:
touch index.html style.css script.js
-
Add content to each:
echo "<!DOCTYPE html>" > index.html echo "body { color: red; }" > style.css echo "console.log('Hello')" > script.js
-
Stage all files at once:
git add . -
Check staged changes:
git status # Shows files as "staged" -
Commit together:
git commit -m "Add initial website files" -
Unstage a file before committing (if needed):
git reset HEAD style.css # Removes style.css from staging git status # Now shows style.css as "not staged"
-
Edit a file:
echo "<h1>Welcome</h1>" >> index.html
-
Check changes before staging:
git diff # Shows unstaged changes -
Stage the modified file:
git add index.html
-
Check staged changes:
git diff --staged # Shows changes in staging -
Commit changes:
git commit -m "Add heading to index.html" -
Undo the last commit (before pushing):
git reset --soft HEAD~1 # Keeps changes staged git reset --mixed HEAD~1 # Unstages changes (default) git reset --hard HEAD~1 # Discards changes completely (use with caution!)
-
Revert a commit (safe undo for pushed commits):
git revert <commit-hash> # Creates a new commit undoing changes
A branch in Git is an independent line of development that allows you to:
- Work on new features without affecting the main codebase
- Fix bugs in isolation
- Experiment safely
- Maintain different versions (e.g., production vs development)
Technical Definition:
A branch is simply a lightweight movable pointer to a specific commit in your repository's history.
-
Isolation of Work
- Developers can work independently without stepping on each other's changes
- Prevents unstable code from breaking the main project
-
Parallel Development
- Multiple features can be developed simultaneously
- Different teams can work on separate components
-
Risk Reduction
- Changes can be tested thoroughly before merging
- Easy to discard unsuccessful experiments
-
Organized Workflow
- Clear separation of concerns (features, releases, hotfixes)
- Better historical tracking of changes
GitFlow is a branching model for Git that provides a structured approach to managing features, releases, and hotfixes. It uses specific branch types with strict rules about how they interact.
main/master- Production-ready code (always deployable)develop- Integration branch for completed features (pre-release state)
feature/*- New functionality (temporary)release/*- Preparation for production (temporary)hotfix/*- Critical production fixes (temporary)
Scenario: Adding user profile management
# Start from develop branch
git checkout develop
git pull origin develop
# Create feature branch
git checkout -b feature/user-profiles
# Develop the feature (multiple commits)
git add .
git commit -m "Add profile creation UI"
git commit -m "Implement profile saving logic"
git push -u origin feature/user-profilesNote: There could be many parallel feature branches (feature/search, feature/checkout, etc.)
# When feature is ready:
# 1. Push final changes
git push origin feature/user-profiles
# 2. Create Pull Request (PR) from:
# feature/user-profiles → develop
# 3. After PR approval and merge:
git checkout develop
git pull origin develop # Get latest with your feature
# 4. Cleanup
git branch -d feature/user-profiles
git push origin --delete feature/user-profilesScenario: Releasing v1.3.0
# From develop branch
git checkout develop
git pull origin develop
# Create release branch
git checkout -b release/v1.3.0
# Final testing/bug fixing (NO new features)
git commit -m "Fix last-minute profile image bug"
# Create PR: release/v1.3.0 → main AND developAfter PR approval:
# Merge to main and tag
git checkout main
git merge --no-ff release/v1.3.0
git tag -a v1.3.0 -m "Release v1.3.0"
# Merge to develop
git checkout develop
git merge --no-ff release/v1.3.0
# Cleanup
git branch -d release/v1.3.0
git push origin main develop --tagsScenario: Critical login bug in production
# From main branch
git checkout main
git pull origin main
# Create hotfix branch
git checkout -b hotfix/login-security
# Make emergency fix
git commit -m "Patch SQL injection vulnerability"
# Create PR: hotfix/login-security → main AND developAfter PR approval:
# Merge to main and tag
git checkout main
git merge --no-ff hotfix/login-security
git tag -a v1.3.1 -m "Hotfix v1.3.1"
# Merge to develop
git checkout develop
git merge --no-ff hotfix/login-security
# Cleanup
git branch -d hotfix/login-security
git push origin main develop --tagsmain
├── v1.2.0
├── v1.3.0 (from release branch)
└── v1.3.1 (from hotfix)
develop
├── feature/user-profiles (merged via PR)
├── release/v1.3.0 (merged via PR)
└── hotfix/login-security (merged via PR)
- All merges happen through PRs for code review
mainalways represents production (only updated via releases/hotfixes)- Features are isolated until fully tested
- Release branches stabilize code before production
- Hotfixes bypass normal flow for emergencies
- Clear separation of development stages
- Controlled integration through PRs
- Traceable releases through tags
- Emergency patching without disrupting feature work
main
└── develop
├── feature/user-auth
├── feature/payment-gateway
├── release/v1.3.0
└── hotfix/login-error
- Starting a new feature →
git checkout -b feature/awesome-feature - Preparing a release →
git checkout -b release/v1.4.0 - Fixing critical bugs →
git checkout -b hotfix/db-connection
A remote repository is a version of your project hosted on:
- GitHub (Microsoft-owned, most popular)
- GitLab (self-hosting options)
- Bitbucket (Atlassian product, good for Jira integration)
Key benefits:
- Cloud backup of your code
- Enables team collaboration
- Provides issue tracking, CI/CD, and project management tools
- Go to github.com
- Create an account or log in
-
Click + → New repository
-
Configure settings:
- Repository name:
my-project(no spaces) - Description: Optional project description
- Visibility: Public (free) or Private
- Initialize with README: ✔️ (Recommended for new projects)
- Add .gitignore: Select language/framework
- License: Optional (MIT, Apache, etc.)
- Repository name:
-
Click Create repository
- HTTPS:
https://github.com/username/my-project.git - SSH:
git@github.com:username/my-project.git
# Initialize local repo
mkdir my-project
cd my-project
git init
# Connect to GitHub
git remote add origin https://github.com/username/my-project.git
# First push
git push -u origin maincd existing-project
# If not already a Git repo:
git init
# Connect to GitHub
git remote add origin https://github.com/username/my-project.git
# First push (may need to pull first if README exists)
git pull origin main --allow-unrelated-histories
git push -u origin maingit remote -v
# Should show:
# origin https://github.com/username/my-project.git (fetch)
# origin https://github.com/username/my-project.git (push)Purpose: Apply specific commits from one branch to another without merging entire histories.
Scenario: Backporting a critical fix from develop to main
# On main branch
git cherry-pick abc1234 # Commit hash from develop
git push origin mainPurpose: Maintain linear project history by replaying commits.
Scenario: Updating a feature branch with latest main changes
git checkout feature/login
git rebase main
# Resolve conflicts if any
git push --force-with-leasePurpose: Shelve uncommitted changes to switch contexts.
Scenario: Emergency bug fix while working on a feature
git stash -u # -u includes untracked files
git checkout hotfix/issue-123
# After fixing...
git checkout feature/login
git stash popPurpose: Stage specific portions of files.
Scenario: Committing only part of a file's changes
git add -p # Opens interactive prompt
# Choose which hunks to stage
git commit -m "Partial feature implementation"Purpose: Clean up local commit history before sharing.
Scenario: Combining WIP commits before PR
git rebase -i HEAD~5
# In editor: squash/split/reword commits
git push --force-with-leasePurpose: Identify the exact commit introducing a bug.
Scenario: Finding regression origin
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
# Test at each step, mark good/bad
git bisect reset # Clean upPurpose: Mark specific points as releases.
Scenario: Creating an annotated release tag
git tag -a v2.3.0 -m "Production release February 2024"
git push --tagsPurpose: Share changes without direct repo access.
Scenario: Sending a fix to a contributor
git format-patch HEAD~1 # Creates 0001-commit-message.patch
# Recipient applies with:
git am 0001-fix.patchPurpose: Multiple working directories from one repo.
Scenario: Simultaneous work on different features
git worktree add ../hotfix-123 hotfix/issue-123
cd ../hotfix-123 # Independent working directoryPurpose: Include external repos as dependencies.
Scenario: Adding a shared component library
git submodule add https://github.com/team/ui-components.git
git commit -m "Add UI component submodule"Purpose: Retrieve lost commits or branches.
Scenario: Restoring accidentally deleted branch
git reflog # Find last known good state
git checkout -b recovered-feature abc1234Purpose: Trigger scripts on Git events.
Scenario: Pre-commit linting
# .git/hooks/pre-commit
#!/bin/sh
npm run lint || exit 1
chmod +x .git/hooks/pre-commit-
Safety First: Always:
git push --force-with-lease # Safer than --force git config --global rerere.enabled true # Reuse recorded resolutions
-
Visualization Tools:
git log --graph --oneline --all # ASCII history graph -
Partial Clones (Large Repos):
git clone --filter=blob:none <repo> # No file contents initially
Sure! Here's an updated and clearer version of the GitHub branch protection setup section for enforcing GitFlow:
To enforce GitFlow effectively in a GitHub repository, branch protection rules must ensure the correct flow of changes through your environment:
- ❌ No direct pushes to
mainordevelop - ✅ All merges via Pull Requests (PRs)
- ✅ Enforce PR reviews and approvals
- 🔁 Only specific branches can target
mainordevelop(e.g.,release/*,hotfix/*→main;feature/*,bugfix/*,hotfix/*→develop)
- Go to your repository on GitHub
- Click Settings → Branches
- Under Branch protection rules, click Add rule
| Setting | Value | Description |
|---|---|---|
| Branch name pattern | main |
Targets the production branch |
| Require a pull request before merging | ✅ Enabled | Enforces code reviews |
| Require approvals | ✅ Enabled (1+ approver) | Mandatory review before merge |
| Dismiss stale pull request approvals | ✅ Enabled | Prevents outdated reviews |
| Require approval from code owners | Optional | For stricter review rules |
| Restrict who can dismiss reviews | Optional | Limit dismissal to admins/maintainers |
| Restrict push access | ✅ Enabled | Prevents direct pushes |
| Allow specified branches to merge | release/*, hotfix/* |
Enforces GitFlow |
| Require status checks to pass | ✅ Recommended | Ties into CI/CD pipelines |
| Require conversation resolution | ✅ Enabled | Ensures all comments are addressed |
| Require linear history | Optional | Avoids merge commits |
| Include administrators | ✅ Enabled | Applies rules to all users |
Same settings as main, except:
| Setting | Value |
|---|---|
| Branch name pattern | develop |
| Allow specified branches to merge | feature/*, bugfix/*, hotfix/* |
## **How This Works in Practice**
### **Allowed Merge Scenario**
1. Developer creates `release/v1.2.0` from `develop`
2. PR created: `release/v1.2.0` → `main`
3. After 1+ approvals and CI passes, merge is allowed
### **Blocked Merge Scenarios**
- ❌ `feature/login` → `main` *(Fails: Not a release/hotfix branch)*
- ❌ Direct push to `main` *(Fails: PR required)*
- ❌ `release/v1.2.0` → `main` with no approvals *(Fails: Approval required)*