~/src/www.mokhan.ca/xlgmokha [main]
cat git-version-control-guide.md
git-version-control-guide.md 21080 bytes | 2010-10-01 12:00
symlink: /dev/random/git-version-control-guide.md

Git Version Control Guide

This is a collection of notes covering Git version control fundamentals and advanced techniques.

Git-SVN Workflow

For teams transitioning from SVN to Git, git-svn provides a bridge:

Initial Setup

# Clone SVN repository
$ git svn clone http://svn-repo -T trunk -b branches -t tags
$ cd svn-repo

Development Workflow

# Update from SVN
$ git svn rebase

# Create and switch to development branch
$ git branch -f development
$ git checkout development

# Make changes
$ gvim hello-world.mkd
$ gvim goodbye-world.mkd

# Commit changes locally
$ git add .
$ git commit -am "added hello world, and good bye"

# Switch back to master and update
$ git checkout master
$ git svn rebase

# Squash merge development changes
$ git merge --squash development
$ git commit # Add squash commit message

# Push to SVN
$ git svn dcommit

# Reset development branch
$ git branch -f development
$ git checkout development

Cleanup Workflow

# Remove files
$ rm goodbye-world.mkd
$ git add -A
$ git commit -am "removed goodbye."

# Update master
$ git checkout master
$ git svn rebase

Repository Management

Merging Git Repositories

When you need to combine multiple repositories while preserving history:

Reference: GitHub Gist

Filter Repository to Specific Directory

# Clone the source repository
$ git clone git@github.com:mokhan/repo1.git
$ cd repo1

# Filter commits to specific directory
$ git filter-branch --subdirectory-filter path/to/subdir -- --all

# Or use git-filter-repo (modern approach)
$ git filter-repo --path path/to/subdir

Merge Repositories

# In target repository
$ git remote add source-repo ../repo1
$ git fetch source-repo

# Merge with history
$ git merge source-repo/main --allow-unrelated-histories

# Clean up
$ git remote remove source-repo

Advanced Filtering

Preserve directory structure during merge:

# Move all files to subdirectory
$ git filter-branch --tree-filter 'mkdir -p new-subdir && git ls-tree --name-only $GIT_COMMIT | xargs -I {} mv {} new-subdir/' HEAD

Core Git Commands

Repository Setup

# Initialize new repository
$ git init

# Clone existing repository
$ git clone <url>
$ git clone --depth 1 <url>  # Shallow clone

# Add remote
$ git remote add origin <url>
$ git remote -v  # List remotes

Basic Workflow

# Check status
$ git status
$ git status -s  # Short format

# Stage changes
$ git add file.txt
$ git add .
$ git add -A  # All changes including deletions

# Commit changes
$ git commit -m "commit message"
$ git commit -am "stage and commit"

# Push changes
$ git push origin main
$ git push -u origin feature-branch  # Set upstream

Branching and Merging

# List branches
$ git branch
$ git branch -a  # Include remote branches
$ git branch -r  # Remote branches only

# Create and switch to branch
$ git checkout -b feature-branch
$ git switch -c feature-branch  # Modern syntax

# Switch branches
$ git checkout main
$ git switch main  # Modern syntax

# Merge branches
$ git merge feature-branch
$ git merge --no-ff feature-branch  # Force merge commit

# Delete branch
$ git branch -d feature-branch
$ git push origin --delete feature-branch  # Delete remote

History and Inspection

# View commit history
$ git log
$ git log --oneline
$ git log --graph --oneline --all

# View changes
$ git diff
$ git diff --staged
$ git diff HEAD~1

# Show specific commit
$ git show <commit-hash>

# Find changes
$ git blame file.txt
$ git log -p file.txt

Advanced Git Techniques

Rebasing

# Rebase current branch onto main
$ git rebase main

# Interactive rebase for last 3 commits
$ git rebase -i HEAD~3

# Continue after resolving conflicts
$ git rebase --continue
$ git rebase --abort  # Cancel rebase

Stashing

# Stash current changes
$ git stash
$ git stash push -m "work in progress"

# List stashes
$ git stash list

# Apply stash
$ git stash pop
$ git stash apply stash@{0}

# Clear stashes
$ git stash clear

Cherry-picking

# Apply specific commit to current branch
$ git cherry-pick <commit-hash>

# Cherry-pick range of commits
$ git cherry-pick A..B

Resetting and Reverting

# Soft reset (keep changes staged)
$ git reset --soft HEAD~1

# Mixed reset (unstage changes)
$ git reset HEAD~1

# Hard reset (discard changes)
$ git reset --hard HEAD~1

# Revert commit (create new commit that undoes changes)
$ git revert <commit-hash>

Git Configuration

Global Configuration

# Set user information
$ 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 configuration
$ git config --list

Aliases

# Create useful aliases
$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.lg "log --graph --oneline --all"

.gitignore

Common patterns for .gitignore:

# Dependencies
node_modules/
vendor/

# Build outputs
dist/
build/
*.min.js

# IDE files
.vscode/
.idea/
*.swp

# OS files
.DS_Store
Thumbs.db

# Environment files
.env
.env.local

# Logs
*.log
logs/

Branching Strategies

Git Flow

Long-running branches:

  • main - Production code
  • develop - Integration branch

Supporting branches:

  • feature/* - New features
  • release/* - Release preparation
  • hotfix/* - Production fixes

GitHub Flow

Simplified workflow:

  1. Create feature branch from main
  2. Make changes and commit
  3. Open pull request
  4. Review and merge to main
  5. Deploy from main

GitLab Flow

Environment-based branches:

  • main - Development
  • pre-production - Staging
  • production - Production

Collaboration Workflows

Fork and Pull Request

# Fork repository on GitHub/GitLab
# Clone your fork
$ git clone git@github.com:yourusername/repo.git

# Add upstream remote
$ git remote add upstream git@github.com:original/repo.git

# Keep fork updated
$ git fetch upstream
$ git checkout main
$ git merge upstream/main

Code Review Process

  1. Create feature branch
  2. Make changes and commit
  3. Push branch to remote
  4. Open pull/merge request
  5. Address review feedback
  6. Merge when approved

Git Hooks

Pre-commit Hook Example

.git/hooks/pre-commit:

#!/bin/sh
# Run tests before commit
npm test
if [ $? -ne 0 ]; then
    echo "Tests failed, commit aborted"
    exit 1
fi

Post-receive Hook Example

#!/bin/sh
# Deploy after push
cd /var/www/app
git pull origin main
npm install
npm run build
sudo systemctl restart app

Troubleshooting

Common Issues

Merge Conflicts:

# View conflicts
$ git status

# Edit conflicted files
$ vim conflicted-file.txt

# Mark as resolved
$ git add conflicted-file.txt
$ git commit

Detached HEAD:

# Create branch from detached HEAD
$ git checkout -b new-branch-name

# Or discard changes and return to branch
$ git checkout main

Undo Last Commit:

# Keep changes
$ git reset --soft HEAD~1

# Discard changes
$ git reset --hard HEAD~1

Repository Maintenance

# Cleanup unnecessary files
$ git gc

# Verify repository integrity
$ git fsck

# Prune remote tracking branches
$ git remote prune origin

# Squash commits interactively
$ git rebase -i HEAD~n

Best Practices

Commit Messages

Follow conventional commit format:

type(scope): subject

body

footer

Types: feat, fix, docs, style, refactor, test, chore

Example:

feat(auth): add OAuth2 integration

Implement OAuth2 authentication flow with Google provider.
Includes login, logout, and token refresh functionality.

Closes #123

Repository Structure

project/
├── .git/
├── .gitignore
├── README.md
├── CHANGELOG.md
├── LICENSE
├── src/
├── tests/
├── docs/
└── scripts/

Security

  1. Never commit secrets (use .gitignore and environment variables)
  2. Sign commits with GPG for verification
  3. Use SSH keys for authentication
  4. Enable two-factor authentication on Git hosting services
  5. Regularly audit repository access and permissions

Performance

  1. Use shallow clones for CI/CD
  2. Enable Git LFS for large files
  3. Keep repositories focused (single responsibility)
  4. Regular maintenance (gc, prune)
  5. Use .gitignore to exclude unnecessary files