The Complete Git Guide: Enterprise Workflows, Best Practices & Cheat Sheet
Whether you are an entry-level software engineer, a senior tech lead, or a DevOps specialist, mastering Git is a core requirement for modern software development. Git is more than just a tool to back up code; it is an environment for team collaboration, quality control, and automated deployment.
This document serves as an end-to-end guide and production-grade cheatsheet covering Git architecture, branch management, commit conventions, release workflows, safety mechanisms, and advanced flag options.
Overview
Estimated Reading Time
35–40 minutes
Prerequisites
- Basic command line knowledge
- Git installed
- A GitHub, GitLab, or Bitbucket account
- Basic understanding of software development workflows (recommended but not required)
What You'll Learn
By the end of this guide, you will be able to:
- Understand Git's internal architecture
- Set up SSH authentication and configure productivity aliases on macOS and Windows
- Choose the right branching strategy for your team
- Work confidently with branches, commits, merges, and rebases
- Recover from common Git mistakes and lost commits
- Follow enterprise-grade Git workflows and best practices
Table of Contents
1. The Git Mental Model
To use Git effectively, you must understand its four primary areas:
+-------------------+ git add +------------------+
| Working Directory | ------------------> | Staging Area |
| (Unstaged Files) | <------------------ | (Index) |
+-------------------+ git restore +------------------+
|
| git commit
v
+-------------------+ git push +------------------+
| Remote Repository | <------------------ | Local Repository |
| (GitHub/GitLab) | ------------------> | (.git) |
+-------------------+ git fetch +------------------+
- Working Directory: Your local workspace where you create, edit, and delete files.
- Staging Area (Index): A draft zone where you organize changes before committing them to history.
- Local Repository (
.git): The local database containing all committed history and branch pointers on your machine. - Remote Repository: The central server (e.g., GitHub, GitLab, Bitbucket) that facilitates team collaboration.
2. Configuration & Repository Initialization
2.1 First-Time Configuration
Set your identity globally across all repositories on your system:
# Set global identity
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# Set default main branch name
git config --global init.defaultBranch main
# Set default push behavior to push only current branch
git config --global push.default simple
# Verify configurations
git config --list
2.2 Authentication Methods
To interact with remote platforms like GitHub or GitLab, you must authenticate using either HTTPS or SSH.
| Method | Pros | Cons | Recommendation |
|---|---|---|---|
| HTTPS | Easy setup; works everywhere behind corporate firewalls. | Requires Personal Access Tokens (PAT); passwords are no longer supported. | Good for quick setup or read-only access. |
| SSH | Seamless authentication via key-pair; no token expiration prompts. | Requires initial key generation and setup. | Recommended for daily development. |
Option A: HTTPS Configuration
When cloning via HTTPS ([https://github.com/org/repo.git](https://github.com/org/repo.git)), modern Git clients use credential helpers to store your Personal Access Token (PAT):
# Enable credential helper (macOS Keychain)
git config --global credential.helper osxkeychain
# Enable credential helper (Windows Credential Manager)
git config --global credential.helper manager
Option B: SSH Configuration (Recommended)
- Generate an SSH Key (Ed25519 recommended):
ssh-keygen -t ed25519 -C "your.email@example.com"
- Start the SSH agent and add your private key:
# macOS / Linux / Windows Git Bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
- Copy the Public Key to Clipboard:
- macOS:
pbcopy < ~/.ssh/id_ed25519.pub - Windows (Git Bash):
cat ~/.ssh/id_ed25519.pub | clip - Windows (PowerShell):
Get-Content~\.ssh\id_ed25519.pub | Set-Clipboard
- Add Key to Remote Platform:
- Go to GitHub / GitLab Settings -> SSH and GPG Keys -> New SSH Key and paste the content.
- Test SSH Connection:
ssh -T git@github.com
# Expected output: Hi username! You've successfully authenticated...
2.3 Setting Up Git Aliases
Aliases create short commands to increase daily development velocity.
Method 1: Git-Native Aliases (Cross-Platform)
These work universally across macOS, Linux, and Windows:
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.sw switch
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.unstage "restore --staged"
Now you can run git st instead of git status.
Method 2: OS Shell Shortcuts
On macOS / Linux (Zsh / Bash)
Add shortcuts to your shell configuration file (~/.zshrc or ~/.bashrc):
# Open profile file
nano ~/.zshrc
# Add the following aliases:
alias g="git"
alias gst="git status"
alias gsw="git switch"
alias gcb="git switch -c"
alias gcm="git commit -m"
alias gpr="git pull --rebase"
alias glog="git log --oneline --graph --all"
# Reload profile
source ~/.zshrc
On Windows (Git Bash)
Edit or create ~/.bashrc in your user directory (C:\Users\YourName\.bashrc):
alias g="git"
alias gst="git status"
alias gsw="git switch"
alias gcb="git switch -c"
alias gcm="git commit -m"
alias gpr="git pull --rebase"
alias glog="git log --oneline --graph --all"
On Windows (PowerShell)
Open your PowerShell profile (notepad $PROFILE) and append:
function g { git $args }
function gst { git status $args }
function gsw { git switch $args }
function gcb { git switch -c $args }
function gcm { git commit -m $args }
function gpr { git pull --rebase $args }
2.4 Initializing and Cloning
# Initialize a new local Git repository in current directory
git init
# Clone a remote repository via HTTPS or SSH
git clone https://github.com/organization/repository.git
git clone git@github.com:organization/repository.git
2.5 Ignoring Files
Always create a .gitignore file at the root of your project to prevent sensitive or build files from entering the repository (e.g., node_modules/, .env, dist/, .DS_Store).
3. Enterprise Branching Strategies
3.1 Comparing Branching Strategies
There is no single "best" branching strategy for every team. Different organizations adopt different workflows depending on their release cadence, deployment model, team size, and compliance requirements.
The four most common strategies are:
| Strategy | Best For | Characteristics |
|---|---|---|
| GitHub Flow | Startups, SaaS, Continuous Deployment | Simple workflow using a single production branch and short-lived feature branches. |
| GitLab Flow | Teams with staging environments | Extends GitHub Flow with environment branches such as staging or production. |
| Gitflow | Enterprise products with scheduled releases | Uses dedicated develop, release, and hotfix branches for controlled release cycles. |
| Trunk-Based Development | Large engineering organizations and CI/CD | Developers integrate into a shared trunk frequently using short-lived branches or direct commits behind feature flags. |
Which one should you choose?
- Choose GitHub Flow if you deploy frequently and maintain a simple workflow.
- Choose GitLab Flow if your deployment pipeline includes multiple environments such as staging and production.
- Choose Gitflow if your organization follows scheduled release cycles and requires dedicated release management.
- Choose Trunk-Based Development if your team practices Continuous Integration and Continuous Deployment (CI/CD) with frequent integrations.
3.2 Gitflow Branch Structure
This guide primarily uses Gitflow because it is still widely adopted by enterprises that maintain scheduled releases and multiple testing environments.
main (Production)
▲
│
release/*
▲
│
develop
▲
│
feature/*
main
The production branch containing stable, production-ready code.
- Protected branch
- No direct commits
- Deployment source
- Tagged with release versions
develop
The integration branch where completed features are merged and tested before a release.
feature/*
Short-lived branches created from develop to implement individual features or bug fixes.
Examples:
feature/user-auth
feature/payment
feature/search
release/*
Created from develop when preparing a production release.
Typical activities include:
- Final QA
- Bug fixes
- Documentation updates
- Version bumping
hotfix/*
Created directly from main to fix critical production issues.
After deployment, the hotfix should be merged back into both:
maindevelop
to prevent future releases from reintroducing the bug.
4. Branch Navigation & Cleanup
Git introduced git switch to replace the multi-purpose git checkout command for branch navigation, reserving git restore for file operations.
Listing Branches
git branch # List local branches
git branch -r # List remote branches (-r = --remotes)
git branch -a # List both local and remote branches (-a = --all)
Branch Creation & Navigation
# Modern Approach (Recommended)
git switch dev # Switch to existing branch
git switch -c feature/user-auth # Create (-c = create) and switch to new branch
# Legacy Approach
git checkout dev # Switch to existing branch
git checkout -b feature/user-auth # Create (-b = branch) and switch to new branch
Deleting Branches
When work on a branch is merged and completed, clean up local and remote environments:
# Local Branch Deletion
git branch -d feature/user-auth # Safe delete (-d): Fails if unmerged changes exist
git branch -D feature/user-auth # Force delete (-D = -d --force): Overrides safety check
# Remote Branch Deletion
git push origin --delete feature/user-auth # Delete branch on remote repository
5. Staging, Status, & File Inspection
Inspecting Changes
git status # Display working tree and staging area state
git status -s # Compact status output (-s = --short)
git diff # Show unstaged changes against staging area
git diff --staged # Show staged changes against last commit
Staging Files (git add)
git add file.js # Stage specific file
git add . # Stage all new, modified, and deleted files in current dir
git add -A # Stage all changes across entire repository (-A = --all)
git add -p # Interactively stage chunks of code (-p = --patch)
Discarding Local Changes (git restore)
git restore file.js # Discard unstaged changes in local file
git restore . # Discard ALL unstaged local changes (DESTRUCTIVE)
git restore --staged file.js # Unstage file (move back to working directory)
6. Commit Conventions & Issue Linking
Commit Flags (git commit)
-m "message": Inline commit message.-a/--all: Automatically stage modified/deleted tracked files before committing.-am "message": Combined shortcut for-aand-m.--amend: Overwrite or modify the most recent commit.
# Standard Commit
git commit -m "feat(auth): add JWT token validation"
# Stage tracked files and commit in one command
git commit -am "fix(cart): correct price rounding error"
# Modify last commit message or add forgotten files
git add forgotten-file.js
git commit --amend --no-edit # Keep original message, add new changes
Conventional Commit Specification
Follow standard commit formatting: <type>(<scope>): <short summary>
feat: A new feature for the user.fix: A bug fix.docs: Documentation only changes.style: Changes that do not affect code logic (formatting, white-space).refactor: Code change that neither fixes a bug nor adds a feature.test: Adding or correcting existing tests.chore: Maintenance tasks, updates to build tools, or dependencies.
Linking Issues (GitHub / GitLab / Jira)
Use trigger keywords in your commit message or Pull Request description to close linked issues automatically when merged into the main branch:
Keywords: Fixes #123, Closes #123, Resolves #123, Refs #123
git commit -m "fix(checkout): resolve Stripe API key exposure issue
Closes #104"
7. Syncing, Merging & Rebasing
Synchronizing Remote Changes
git fetch origin # Fetch remote metadata without modifying local code
git pull origin dev # Fetch and automatically merge remote branch into local
git pull --rebase origin dev # Fetch and apply local commits ON TOP of remote commits
Why git pull --rebase?
By default, git pull performs a fetch followed by a merge. If both you and the remote branch have new commits, Git creates an additional merge commit, which can clutter the commit history over time.
Using git pull --rebase instead rewrites your local commits so they are replayed on top of the latest remote commits, resulting in a cleaner and more linear history.
Example:
Before pulling:
origin/dev
A──B──C
local
A──B──D──E
Using git pull:
A──B──C────────M
\ /
D────E
Using git pull --rebase:
A──B──C──D'──E'
The second history is easier to read, debug, and review because it avoids unnecessary merge commits.
Enterprise Best Practice
Use
git pull --rebaseon your local feature branches to keep commit history clean and minimize unnecessary merge commits.
When NOT to use it
Avoid rebasing commits that have already been shared with your team on a public branch, as rebasing rewrites commit history. Once a branch is shared, prefer merging unless your team's workflow explicitly allows rebasing.
Merging Strategies
# Standard Merge (creates a explicit merge commit)
git switch dev
git merge --no-ff feature/user-auth -m "merge: feature/user-auth into dev"
# Squash Merge (combines all branch commits into a single unified commit)
git switch dev
git merge --squash feature/user-auth
git commit -m "feat(auth): complete user authentication module"
--no-ff(No Fast-Forward): Ensures a merge commit is recorded even if the merge could be fast-forwarded. Preserves the history of the feature branch.--squash: Flattens multiple micro-commits on a feature branch into one single commit before integrating.
8. Releases & Semantic Versioning
8.1 Versioning Format
Deployments are tracked using Git tags using Semantic Versioning (vMAJOR.MINOR.PATCH):
MAJOR: Incompatible API changes.MINOR: Added functionality in a backward-compatible manner.PATCH: Backward-compatible bug fixes.
8.2 Managing Tags
# Create an annotated tag (-a = annotated, -m = message)
git tag -a v1.0.0 -m "Production Release v1.0.0"
# List tags
git tag -l # List all tags (-l = --list)
# Push tags to remote
git push origin v1.0.0 # Push specific tag
git push origin --tags # Push all local tags to remote
9. End-to-End Enterprise Workflow
9.1 Scenario A: Developing a New Feature
# 1. Update dev branch
git switch dev
git pull --rebase origin dev
# 2. Create feature branch
git switch -c feature/payment-gateway
# 3. Work, stage, and commit changes
git add .
git commit -m "feat(payment): implement Stripe payment intent handler Closes #45"
# 4. Sync with dev before pushing (to catch potential conflicts early)
git fetch origin
git rebase origin/dev
# 5. Push branch and set upstream tracking (-u = --set-upstream)
git push -u origin feature/payment-gateway
# 6. Open Pull Request (PR) on GitHub/GitLab targeting 'dev'
# 7. Once approved and merged, clean up local branch
git switch dev
git pull origin dev
git branch -d feature/payment-gateway
9.2 Scenario B: Emergency Production Hotfix
# 1. Branch directly from production main
git switch main
git pull origin main
git switch -c hotfix/auth-bypass-vulnerability
# 2. Apply fix and commit
git commit -am "fix(security): patch authentication bypass vulnerability Closes #911"
# 3. Merge hotfix into main, tag it, and push
git switch main
git merge --no-ff hotfix/auth-bypass-vulnerability -m "merge: hotfix v1.0.1"
git tag -a v1.0.1 -m "Hotfix Release v1.0.1"
git push origin main --tags
# 4. Backport hotfix into dev so changes aren't lost in future releases
git switch dev
git merge --no-ff hotfix/auth-bypass-vulnerability -m "merge: backport hotfix v1.0.1 to dev"
git push origin dev
# 5. Clean up hotfix branch
git branch -d hotfix/auth-bypass-vulnerability
git push origin --delete hotfix/auth-bypass-vulnerability
10. Emergency Room: Undoing Mistakes & Data Recovery
Undoing Commits (git reset)
| Command | Working Directory | Staging Area | Commit History | Use Case |
|---|---|---|---|---|
git reset --soft HEAD~1 | Kept | Kept (Staged) | Undone | Redo commit message or group commits. |
git reset --mixed HEAD~1 (Default) | Kept | Cleared | Undone | Modify staged files before re-committing. |
git reset --hard HEAD~1 | Destroyed | Cleared | Undone | Dangerous. Completely destroy last commit and all local changes. |
Reverting Public Commits (git revert)
If a bad commit is already pushed to a shared remote branch (main or dev), do not use reset. Use git revert to create a new inverse commit safely:
# Create a new commit that safely reverses changes from specified commit
git revert <commit-hash>
git push origin main
Temporary Workspace Storage (git stash)
Save dirty working directory state temporarily without committing:
git stash save "Work in progress on user checkout" # Save unstaged/staged changes
git stash list # List saved stashes
git stash pop # Apply last stash and remove it from stash list
git stash apply # Apply last stash but keep it in stash list
git stash drop # Remove last stash
Recovery of Lost Commits (git reflog)
Git keeps a log of every HEAD position movement. Even if you perform a git reset --hard, you can recover lost commits via reflog:
git reflog # Display history of HEAD moves
# Output example: HEAD@{1}: reset: moving to HEAD~1
# Output example: HEAD@{2}: commit: feat(user): add user page
# Restore lost commit using hash or reference
git reset --hard HEAD@{2}
11. Git Command Reference & Cheatsheet
| Category | Command | Common Flags | Description |
|---|---|---|---|
| Configuration | git config | --global<br>--list | Configure Git globally or locally, and display current configuration. |
| Repository | git init | — | Initialize a new Git repository. |
git clone | <url> | Clone an existing remote repository. | |
| Branching | git switch | -c <branch> | Create and switch to a new branch. |
git branch | -a<br>-r<br>-d<br>-D | List all branches, list remote branches, safely delete a merged branch, or force delete a branch. | |
| Inspection | git status | -s | Display repository status in short format. |
git diff | --staged | Compare unstaged or staged changes. | |
git log | --oneline<br>--graph<br>--all | View commit history in a compact graph format. | |
| Staging | git add | .<br>-A<br>-p | Stage all files, all repository changes, or interactively stage selected hunks. |
git restore | --staged<br>. | Unstage files or discard unstaged changes. | |
| Commit | git commit | -m<br>-am<br>--amend | Create commits, commit tracked changes directly, or modify the latest commit. |
| Synchronization | git fetch | --prune (-p) | Fetch remote changes and remove deleted remote-tracking branches. |
git pull | --rebase | Fetch and replay local commits on top of the latest remote commits. | |
git push | -u<br>--tags<br>--delete<br>--force-with-lease | Set upstream branch, push tags, delete remote branches, or safely force-push. | |
| Merging | git merge | --no-ff<br>--squash | Create explicit merge commits or squash commits into a single commit. |
| Tagging | git tag | -a<br>-l | Create annotated tags or list existing tags. |
| Recovery | git reset | --soft<br>--mixed<br>--hard | Undo commits while preserving, unstaging, or discarding local changes. |
git revert | <commit> | Safely reverse a commit by creating a new commit. | |
git reflog | — | View HEAD history and recover lost commits. | |
git stash | push<br>pop<br>list<br>apply | Temporarily save and restore uncommitted work. |
12. Core Operational Rules for Engineers
- **Protect
mainanddev**: Require Pull Requests and mandatory code reviews before merging. - Pull with Rebase: Keep your local history clean using
git pull --rebase origin dev. - Commit Atomically: Each commit should address a single, logical change.
- **Use
force-with-leaseoverforce**: When pushing rebased branches, usegit push --force-with-leaseto avoid overwriting a teammate's remote work. - Clean up Merged Branches: Keep remote and local repositories free of abandoned feature branches using
git branch -dandgit push origin --delete.