Git is powerful. It’s also easy to mess up. Here are workflows that keep repositories clean and teams productive.
Solo Workflow# For personal projects, keep it simple:
1
2
3
4
5
6
# Work on main, commit often
git add -A
git commit -m "Add user authentication"
# Push when ready
git push origin main
Use branches for experiments:
1
2
3
4
git checkout -b experiment/new-ui
# work...
git checkout main
git merge experiment/new-ui # or delete if failed
Feature Branch Workflow# The most common team pattern:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Start feature from main
git checkout main
git pull origin main
git checkout -b feature/user-profile
# Work and commit
git add -A
git commit -m "Add profile page layout"
git commit -m "Add avatar upload"
# Push branch
git push origin feature/user-profile
# Create PR, get reviews, merge
Keep Branches Updated# 1
2
3
4
5
6
7
8
9
# Option 1: Merge main into branch
git checkout feature/user-profile
git fetch origin
git merge origin/main
# Option 2: Rebase (cleaner history)
git checkout feature/user-profile
git fetch origin
git rebase origin/main
Commit Message Convention# t L F y o i p n x e g e ( e s s r c # o e 1 p x 2 e p 3 ) l : a n s a h t o i r o t n d i e f s c n r e i e p d t e i d o . n
Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formattingrefactor: Code restructuretest: Testschore: MaintenanceExamples:
1
2
3
git commit -m "feat(auth): add password reset flow"
git commit -m "fix(api): handle null response from payment provider"
git commit -m "docs: update API authentication section"
Interactive Rebase# Clean up before merging:
1
2
# Squash last 5 commits
git rebase -i HEAD~5
In the editor:
p s s p s i q q i q c u u c u k a a k a s s s a h h j h b k c d g l m 1 e h 0 n 2 f i 1 o 3 4 7 2 3 5 8 4 A 6 9 A 5 d d d F A d F i d i u x d u x s s e t v e c r y a r o p l n m o i c t o d o r d a n o e t t l l i r l o o e n l r l e b r u g
Result: 2 clean commits instead of 5 messy ones.
Stashing Work# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Save work without committing
git stash
# List stashes
git stash list
# Apply latest stash
git stash pop
# Apply specific stash
git stash apply stash@{ 2}
# Stash with message
git stash push -m "WIP: user profile refactor"
# Stash specific files
git stash push -m "partial" src/auth.py
Handling Merge Conflicts# 1
2
3
4
5
6
7
8
9
10
# When merge fails
git merge feature-branch
# CONFLICT in file.py
# Edit the file, resolve conflicts
# Look for <<<<<<< ======= >>>>>>>
# Mark as resolved
git add file.py
git commit # Completes the merge
Or abort:
Undoing Things# Undo Last Commit (Keep Changes)# 1
git reset --soft HEAD~1
Undo Last Commit (Discard Changes)# 1
git reset --hard HEAD~1
Undo Specific Commit (Create New Commit)# Discard Uncommitted Changes# 1
2
3
4
5
6
7
8
9
# Single file
git checkout -- file.py
# All files
git checkout -- .
# Or using restore (modern)
git restore file.py
git restore .
Recover Deleted Branch# 1
2
3
4
5
# Find the commit
git reflog
# Recreate branch
git checkout -b recovered-branch abc123
Git Aliases# Add to ~/.gitconfig:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[alias]
st = status -sb
co = checkout
br = branch
ci = commit
unstage = reset HEAD --
last = log -1 HEAD
lg = log --oneline --graph --decorate -20
branches = branch -a
tags = tag -l
stashes = stash list
amend = commit --amend --no-edit
undo = reset --soft HEAD~1
discard = checkout --
wip = !git add -A && git commit -m 'WIP'
publish = !git push -u origin $(git branch --show-current)
Usage:
1
2
3
4
5
git st # Short status
git lg # Pretty log
git amend # Amend without changing message
git undo # Undo last commit
git publish # Push and set upstream
Git Hooks# Automate checks before commits:
1
2
3
4
5
6
7
8
9
# .git/hooks/pre-commit
#!/bin/bash
# Run linter
npm run lint || exit 1
# Run tests
npm test || exit 1
echo "Pre-commit checks passed"
Make executable:
1
chmod +x .git/hooks/pre-commit
Use Husky for team-shared hooks:
1
2
3
npm install husky --save-dev
npx husky install
npx husky add .husky/pre-commit "npm run lint"
Gitignore Patterns# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Dependencies
node_modules/
vendor/
.venv/
# Build output
dist/
build/
*.pyc
__pycache__/
# Environment
.env
.env.local
*.local
# IDE
.idea/
.vscode/
*.swp
# OS
.DS_Store
Thumbs.db
# Logs
*.log
logs/
# Secrets (never commit these)
*.pem
*.key
secrets/
Global gitignore:
1
git config --global core.excludesfile ~/.gitignore_global
Working with Remotes# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
# List remotes
git remote -v
# Add remote
git remote add upstream https://github.com/original/repo.git
# Fetch from upstream
git fetch upstream
# Merge upstream changes
git merge upstream/main
# Change remote URL
git remote set-url origin git@github.com:user/repo.git
Cherry-Pick# Apply specific commits to another branch:
1
2
3
4
5
6
7
8
git checkout main
git cherry-pick abc123
# Multiple commits
git cherry-pick abc123 def456 ghi789
# Range of commits
git cherry-pick abc123..ghi789
Bisect# Find the commit that introduced a bug:
1
2
3
4
5
6
7
8
9
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.0.0 # This version worked
# Git checks out commits, you test each one
git bisect good # or bad
# Eventually finds the culprit
git bisect reset # Return to normal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# List tags
git tag
# Create annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0"
# Create lightweight tag
git tag v1.0.0
# Push tags
git push origin v1.0.0
git push origin --tags
# Delete tag
git tag -d v1.0.0
git push origin --delete v1.0.0
Worktrees# Work on multiple branches simultaneously:
1
2
3
4
5
6
7
8
9
# Create worktree for another branch
git worktree add ../project-hotfix hotfix-branch
# Work in separate directory
cd ../project-hotfix
# make changes, commit, push
# Remove when done
git worktree remove ../project-hotfix
Quick Reference# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Start
git clone URL # Clone repo
git init # New repo
# Daily
git status # What's changed
git add -A # Stage all
git commit -m "message" # Commit
git push # Push
# Branches
git checkout -b name # Create branch
git checkout main # Switch
git merge branch # Merge
git branch -d name # Delete
# Sync
git fetch # Get remote changes
git pull # Fetch + merge
git push # Send changes
# History
git log --oneline # Short log
git diff # Show changes
git blame file # Who changed what
# Fix
git reset --soft HEAD~1 # Undo commit
git stash # Save for later
git checkout -- file # Discard changes
Good git habits prevent disasters. Learn the patterns, save yourself hours of recovery.