Post

Git Workflow Best Practices - A Professional Guide

A practical guide to Git workflows for everyday development, covering essential commands, environment management, and team collaboration.

Git Workflow Best Practices - A Professional Guide

“Git is like a time machine for your code - use it wisely to track changes and collaborate effectively.”

Table of Contents

🧠 Beginner vs Professional Mindset

BeginnerProfessional
Commits everything at onceMakes small, logical commits
Uses default commit messagesWrites structured, descriptive messages
Pushes directly to main branchUses feature branches and PRs
Fixes conflicts without understandingUnderstands and resolves conflicts carefully
Relies on GUI tools exclusivelyEmbraces CLI for precision and automation
Fears complex Git operationsMasters rebase, cherry-pick, and bisect
Ignores Git hooks and automationLeverages Git hooks for quality checks
Struggles with merge conflictsPlans work to minimize conflicts

Tip: The difference between a beginner and professional isn’t the commands they know, but how they think about version control as part of their workflow.

🧠 Why This Matters

Understanding Git workflows properly matters because:

  1. History is valuable - Your commit history is documentation of how and why code evolved
  2. Collaboration requires clarity - Teams need to understand each other’s changes
  3. Recovery depends on good practices - When things go wrong, clean history helps pinpoint issues
  4. CI/CD integration - Modern deployment relies on well-structured Git workflows
  5. Code quality - Proper review processes improve overall code health

As projects grow in complexity and team size, these practices become not just helpful but essential.

🏁 Starting Your Day

Scenario: You’re starting work on an existing project

First, you need to get the latest code and see what’s changed:

1
2
3
4
5
6
7
8
9
# Check what branch you're on
git status

# Get the latest changes from main
git checkout main
git pull origin main

# See recent changes
git log --oneline -n 5

Tip: Always start with a clean slate by pulling the latest changes. This prevents merge conflicts later.

Scenario: You need to check what you worked on yesterday

1
2
3
4
5
# See your recent commits
git log --author="your.name" --since="1 day ago"

# See what files changed
git diff --name-only HEAD~1 HEAD

💻 Working on Features

Scenario: Starting a new feature

When you’re ready to work on a new feature, create a dedicated branch:

1
2
3
4
5
6
# Create and switch to new feature branch
git checkout -b feature/user-login

# Make your changes and save them
git add .
git commit -m "feat: add user login form"

Note: Always create feature branches from the latest main branch to avoid conflicts.

Scenario: You’ve made changes and want to save your work

1
2
3
4
5
6
7
8
9
10
11
# See what files changed
git status

# Add specific files
git add login.html login.css

# Or add all changes
git add .

# Save your changes with a clear message
git commit -m "feat: add login form styling"

Scenario: You need to update your feature with latest changes

1
2
3
4
5
6
7
8
9
10
11
# Get latest changes from main
git checkout main
git pull origin main

# Update your feature branch
git checkout feature/user-login
git rebase main

# If there are conflicts, fix them and continue
git add .
git rebase --continue

⚠️ Handling Mistakes

Scenario: You committed to the wrong branch

1
2
3
4
5
6
7
# Create new branch with your changes
git checkout -b feature/your-changes
git push -u origin feature/your-changes

# Reset the original branch
git checkout main
git reset --hard origin/main

Scenario: You want to undo your last commit

1
2
3
4
5
# Keep your changes in working directory
git reset --soft HEAD~1

# Or discard changes completely
git reset --hard HEAD~1

Scenario: You need to temporarily save your work

1
2
3
4
5
6
7
8
# Save current work
git stash

# List your stashes
git stash list

# Get back to work
git stash pop

👥 Team Collaboration

Scenario: You’re ready to share your work

1
2
3
4
5
# Push your feature branch
git push origin feature/user-login

# Create a pull request
# (This is usually done through your Git platform UI)

Scenario: You need to review someone’s code

1
2
3
4
5
6
# Get their branch
git fetch origin
git checkout feature/their-feature

# See what changed
git diff main...feature/their-feature

🌳 Environment Management

Understanding Different Environments

EnvironmentPurposeWhen to Use
mainProductionLive, customer-facing code
stagingPre-productionTesting before going live
uatUser AcceptanceClient/team review
developDevelopmentDaily work

Scenario: Moving code through environments

1
2
3
4
5
6
7
8
9
10
11
# Feature is ready for testing
git checkout staging
git merge feature/user-login

# After testing, move to UAT
git checkout uat
git merge staging

# Finally, release to production
git checkout main
git merge uat

📘 Documentation Approach

Professional Git users know how to find and use documentation effectively:

1
2
3
4
5
6
7
8
# View built-in Git help
git help <command>

# View short help for a command
git <command> -h

# Visit official documentation
# https://git-scm.com/docs

Key documentation resources every Git professional uses:

  1. Official Git documentation - Comprehensive and authoritative
  2. Pro Git book - Free, detailed book from the Git maintainers
  3. Your team’s workflow documentation - Specific to your project
  4. Git repository’s README and CONTRIBUTING files - Project-specific guidelines

Tip: Create a personal cheatsheet of Git commands you use frequently with examples.

✅ Safe Git Commands

Just like in Linux, Git provides ways to test commands before executing them:

CommandSafe AlternativePurpose
git mergegit merge --no-commit --no-ffTest merge without finalizing
git pushgit push --dry-runSimulate push without sending
git rmgit rm --dry-runSee what would be removed
git cleangit clean -nShow what untracked files would be removed
git addgit add -nShow what would be added
git rebaseCreate temporary branchTest rebase on temporary branch
git resetBackup branch firstCreate safety branch before resetting

Real-world Example: Safe Cleaning

1
2
3
4
5
6
7
8
# First, see what would be removed
git clean -n

# If it looks good, actually remove the files
git clean -f

# To also remove directories
git clean -fd

⚙️ Git Configuration

Professional Git users customize their environment for efficiency:

1
2
3
4
5
6
7
8
9
10
11
12
# Set your identity
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# Set default editor
git config --global core.editor "vim"

# Set default branch name
git config --global init.defaultBranch main

# List all settings
git config --list

Essential configuration settings:

1
2
3
4
5
6
7
8
9
10
11
# Set colorful output
git config --global color.ui auto

# Set automatic correction of commands
git config --global help.autocorrect 20

# Set automatic rebase on pull
git config --global pull.rebase true

# Configure global .gitignore
git config --global core.excludesfile ~/.gitignore_global

✅ Best Practices

Writing Good Commit Messages

A good commit message explains what changed and why:

1
2
3
4
5
6
7
feat: add user login form

- Add HTML form structure
- Style with CSS
- Add basic validation

Closes #123

Conventional Commits

Professional teams often use a commit message convention:

TypeDescription
feat:New feature
fix:Bug fix
docs:Documentation
style:Formatting changes
refactor:Code restructuring
test:Adding/modifying tests
chore:Maintenance tasks

Branch Naming Conventions

  • Features: feature/login-form
  • Bugs: fix/login-error
  • Hotfixes: hotfix/prod-issue
  • Releases: release/v1.2.0

Code Review Best Practices

  1. Review in small batches - Aim for PRs under 400 lines
  2. Use descriptive PR templates - Include context, changes, and testing
  3. Automated checks first - Let CI/CD run before manual review
  4. Review tests with code - Ensure proper test coverage
  5. Follow team standards - Be consistent with team practices

Everyday Tips

  1. Start Fresh: Always pull latest changes before starting work
  2. Commit Often: Small, focused commits are easier to review
  3. Write Clearly: Good commit messages help everyone understand changes
  4. Stay Updated: Regularly update your feature branches
  5. Test First: Always test before pushing changes
  6. Review Your Work: Check your changes before creating PRs

🔧 Git Aliases

Professional Git users create aliases for common commands:

1
2
3
4
5
6
7
8
9
# Add these to your .gitconfig file
[alias]
    st = status
    co = checkout
    br = branch
    ci = commit
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
    unstage = reset HEAD --
    last = log -1 HEAD

Using aliases saves time and reduces typing:

1
2
3
4
5
# Instead of
git status

# Just type
git st

🚀 Advanced Git Techniques

Interactive Rebasing

1
2
3
4
5
6
7
8
9
10
# Rewrite the last 3 commits
git rebase -i HEAD~3

# Commands available in interactive rebase:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# d, drop = remove commit

Cherry-picking

1
2
3
4
5
# Apply a specific commit to current branch
git cherry-pick abc123

# Cherry-pick without committing
git cherry-pick --no-commit abc123

Git Bisect for Debugging

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Start the bisect process
git bisect start

# Mark current version as bad
git bisect bad

# Mark a known good commit
git bisect good abc123

# Git will check out commits for you to test
# After testing, mark as good or bad
git bisect good  # or
git bisect bad

# When done, reset to original state
git bisect reset

🔄 Git Hooks

Git hooks automate tasks during specific points in Git’s workflow:

1
2
3
4
# Common hooks locations
.git/hooks/pre-commit
.git/hooks/pre-push
.git/hooks/commit-msg

Example: Pre-commit Hook for Linting

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# .git/hooks/pre-commit

# Run linter on staged files
files=$(git diff --cached --name-only --diff-filter=ACM "*.js" "*.jsx")
if [ -n "$files" ]; then
    echo "Running linter on staged files..."
    npx eslint $files
    if [ $? -ne 0 ]; then
        echo "Linting failed. Please fix errors before committing."
        exit 1
    fi
fi

Example: Commit Message Hook for Conventional Commits

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
# .git/hooks/commit-msg

commit_msg=$(cat "$1")
pattern='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?:\s.+'

if ! [[ "$commit_msg" =~ $pattern ]]; then
    echo "Error: Commit message must follow conventional commits format."
    echo "Example: feat: add user authentication"
    exit 1
fi

Note: To share hooks with your team, store them in your repository and use a script to symlink them into .git/hooks/.

🔧 Troubleshooting Approach

Professional Git users follow a systematic approach to troubleshooting:

1. Understand the Current State

1
2
3
4
5
6
7
8
9
# Check current branch and status
git status

# Check recent history
git log --oneline -n 5

# Check remote branches
git remote -v
git branch -avv

2. Common Problems and Solutions

ProblemDiagnosisSolution
Can’t pushgit push gives errorPull first with git pull --rebase
Lost commitsCan’t see recent workUse git reflog to find them
Merge conflictsAutomatic merge failedUse git mergetool or resolve manually
Detached HEADHEAD not on branchgit checkout -b new-branch to save work
Accidental commitsCommitted wrong changesgit reset --soft HEAD~1 to undo

3. Recovering Lost Work

1
2
3
4
5
6
7
8
# Find "lost" commits
git reflog

# Recover a deleted branch
git checkout -b recovered-branch <commit-hash>

# Recover uncommitted changes
git fsck --lost-found

🔍 Using Regex with Git

Regular expressions are powerful tools in Git for searching and filtering:

Advanced Grep in Git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Search for pattern in all files
git grep "function login"

# Case insensitive search
git grep -i "error"

# Show line numbers
git grep -n "TODO"

# Search in specific files
git grep "api call" -- "*.js"

# Use extended regex
git grep -E "function (login|logout)"

Regex in .gitignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Ignore all log files
*.log

# Except production logs
!production.log

# Ignore all directories named 'temp' anywhere
**/temp

# Ignore all .tmp files in the root directory only
/*.tmp

# Ignore all .cache directories
**/.cache/

Regex in Git Commands

1
2
3
4
5
6
7
8
# Find commits with messages matching pattern
git log --grep="fix: auth"

# Find commits that add or remove specific pattern
git log -S"login function"

# Find commits that change lines matching pattern
git log -G"function user(.*)"

📌 Final Thought

“A Git master doesn’t just track code; they tell the story of how it evolved.”

Git isn’t just about storing code—it’s about preserving the narrative of your project’s development. By adopting professional Git practices, you’re not only making your daily work more efficient but also creating a valuable historical record that helps future developers (including your future self) understand the what, how, and why of each change.

The difference between using Git as a simple backup tool and leveraging it as a comprehensive version control system lies in mastering these professional workflows and integrating them into your daily development practice.

This post is licensed under CC BY 4.0 by the author.