Version control with Git for efficient collaboration and code management
15 min read
Introduction to Git
Git is a distributed version control system that enables multiple developers to work on the same codebase without conflicts. It tracks changes, maintains history, and facilitates collaboration, making it essential for modern software development and DevOps practices.
Git Architecture and Core Concepts
Key Terminology
- Repository: Storage location for your project and its history
- Commit: Snapshot of changes at a specific point in time
- Branch: Independent line of development
- Merge: Combining changes from different branches
- Remote: Repository hosted on a server or service
- Clone: Creating a local copy of a remote repository
Git Installation and Setup
Installing Git
# Ubuntu/Debian sudo apt update sudo apt install git # RHEL/CentOS sudo yum install git # macOS brew install git # Windows # Download from https://git-scm.com/download/win # Verify installation git --version
Basic Configuration
# Global configuration git config --global user.name "Your Name" git config --global user.email "your.email@example.com" git config --global init.defaultBranch main # Editor preferences git config --global core.editor "code --wait" # VS Code git config --global core.editor "vim" # Vim # Useful aliases git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.unstage 'reset HEAD --' git config --global alias.last 'log -1 HEAD' # View configuration git config --list
Basic Git Workflow
Repository Initialization
# Create new repository mkdir my-project cd my-project git init # Clone existing repository git clone https://github.com/username/repository.git git clone https://github.com/username/repository.git my-local-folder # Check repository status git status
Basic Commands
# Adding files to staging area git add filename.txt # Add specific file git add . # Add all files in current directory git add *.js # Add all JavaScript files git add -A # Add all changes (new, modified, deleted) # Committing changes git commit -m "Initial commit" git commit -m "Add user authentication feature" # Good commit message structure: # feat: add user authentication # # - Implement JWT token-based authentication # - Add login/logout endpoints # - Include password hashing with bcrypt # # Fixes #123 # Viewing history git log git log --oneline git log --graph --oneline --all git log -p filename.txt # Show changes for specific file
Branching Strategies
GitFlow Workflow
# Main branches main/master - Production-ready code develop - Integration branch for features # Supporting branches feature/* - New features release/* - Release preparation hotfix/* - Production fixes # Example workflow git checkout -b feature/user-auth # Create feature branch # ... develop feature ... git checkout develop git merge --no-ff feature/user-auth # Merge feature git branch -d feature/user-auth # Delete feature branch
Trunk-Based Development
# Short-lived feature branches git checkout -b feature/quick-fix # ... make changes ... git checkout main git merge feature/quick-fix # Or using rebase git checkout feature/quick-fix git rebase main git checkout main git merge feature/quick-fix
Advanced Branch Management
Branch Operations
# Creating and switching branches git branch feature/new-feature # Create branch git checkout feature/new-feature # Switch to branch git checkout -b feature/new-feature # Create and switch # Listing branches git branch # Local branches git branch -r # Remote branches git branch -a # All branches # Deleting branches git branch -d feature/old # Delete merged branch git branch -D feature/abandoned # Force delete unmerged branch # Renaming branches git branch -m old-name new-name # Tracking remote branches git branch -u origin/feature/new-feature git push --set-upstream origin feature/new-feature
Stashing Changes
# Save uncommitted changes temporarily
git stash # Stash changes
git stash save "Work in progress" # Stash with message
# List stashes
git stash list
# Apply stashed changes
git stash apply # Apply latest stash
git stash apply stash@{1} # Apply specific stash
# Create branch from stash
git stash branch new-branch
# Clear stashes
git stash drop stash@{0} # Delete specific stash
git stash clear # Delete all stashes
Merging and Rebasing
Merge Strategies
# Fast-forward merge (linear history) git checkout main git merge feature/simple # Three-way merge (merge commit) git merge --no-ff feature/complex # Squash merge (single commit) git merge --squash feature/multiple-commits git commit -m "Complete feature implementation" # Resolving merge conflicts # When conflict occurs: # 1. Edit conflicted files # 2. Mark as resolved: git add filename.txt # 3. Complete merge: git commit
Rebasing
# Rebase feature branch onto main git checkout feature/new-feature git rebase main # Interactive rebase (rewrite history) git rebase -i HEAD~3 # Rebase last 3 commits # Interactive rebase commands: # pick - use commit # reword - use commit, but edit commit message # edit - use commit, but stop for amending # squash - use commit, but meld into previous commit # fixup - like squash, but discard commit message # drop - remove commit # Rebase with conflict resolution git rebase main # Resolve conflicts, then: git add . git rebase --continue # Or abort: git rebase --abort
Remote Repository Management
Working with Remotes
# Adding remote repositories git remote add origin https://github.com/user/repo.git git remote add upstream https://github.com/original/repo.git # Viewing remotes git remote -v # Fetching changes git fetch origin # Download changes without merging git fetch --all # Fetch from all remotes # Pulling changes git pull origin main # Fetch and merge git pull --rebase origin main # Fetch and rebase # Pushing changes git push origin main # Push to main branch git push origin feature/new # Push feature branch git push -u origin feature/new # Push and set upstream # Force push (use with caution) git push --force-with-lease origin main
Collaboration Patterns
# Forking workflow (open source) # 1. Fork repository on GitHub # 2. Clone your fork git clone https://github.com/your-username/repo.git # 3. Add upstream remote git remote add upstream https://github.com/original/repo.git # 4. Sync with upstream git fetch upstream git merge upstream/main # Shared repository workflow (team) # 1. Clone shared repository git clone https://github.com/team/repo.git # 2. Create feature branch git checkout -b feature/your-feature # 3. Push and create PR git push -u origin feature/your-feature
Advanced Git Operations
Undoing Changes
# Undo unstaged changes git checkout -- filename.txt # Restore file from last commit git restore filename.txt # Newer way (Git 2.23+) # Undo staged changes git reset HEAD filename.txt # Unstage file git restore --staged filename.txt # Newer way # Amend last commit git commit --amend # Edit last commit message git commit --amend --no-edit # Add changes to last commit # Reset to previous commit git reset --soft HEAD~1 # Keep changes staged git reset --mixed HEAD~1 # Keep changes unstaged (default) git reset --hard HEAD~1 # Discard all changes # Revert a commit (safe for shared history) git revert commit-hash # Create new commit that undoes changes
Git History Manipulation
# Interactive rebase for history editing git rebase -i HEAD~5 # Changing multiple commit messages # In rebase interactive mode, change 'pick' to 'reword' # Squashing commits # In rebase interactive mode, change 'pick' to 'squash' or 'fixup' # Reordering commits # In rebase interactive mode, reorder the lines # Splitting commits # In rebase interactive mode, change 'pick' to 'edit' # Then: git reset HEAD~1, make multiple commits, git rebase --continue
Git Hooks
Common Hooks
# Pre-commit hook (.git/hooks/pre-commit)
#!/bin/bash
# Run tests before commit
npm test
if [ $? -ne 0 ]; then
echo "Tests failed! Commit aborted."
exit 1
fi
# Pre-push hook (.git/hooks/pre-push)
#!/bin/bash
# Check if main branch is protected
current_branch=$(git symbolic-ref --short HEAD)
if [ "$current_branch" = "main" ]; then
echo "Direct pushes to main are not allowed. Use PR instead."
exit 1
fi
# Commit-msg hook
#!/bin/bash
# Validate commit message format
MSG=$(cat $1)
if ! echo "$MSG" | grep -qE "^(feat|fix|docs|style|refactor|test|chore): "; then
echo "Invalid commit message format!"
echo "Use: feat|fix|docs|style|refactor|test|chore: description"
exit 1
fi
Client-Side Hooks
# pre-commit: Run before commit message # prepare-commit-msg: Run before commit message editor # commit-msg: Run after commit message is created # post-commit: Run after commit is completed # pre-rebase: Run before rebase # post-merge: Run after successful merge # pre-push: Run before push to remote
Git in CI/CD Pipelines
Git Commands in Automation
# GitHub Actions example
name: CI Pipeline
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v35
- name: Run tests for changed files
run: |
if [[ "${{ steps.changed-files.outputs.all_changed_files }}" ]]; then
echo "Changed files: ${{ steps.changed-files.outputs.all_changed_files }}"
# Run specific tests based on changed files
fi
# GitLab CI example
stages:
- test
- deploy
test:
stage: test
script:
- git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA
- npm test
deploy:
stage: deploy
script:
- git checkout main
- git pull origin main
- ./deploy.sh
Git Best Practices
Commit Message Conventions
# Conventional Commits specification <type>[optional scope]: <description> [optional body] [optional footer(s)] # Types: # feat: New feature # fix: Bug fix # docs: Documentation only changes # style: Changes that do not affect meaning (white-space, formatting) # refactor: Code change that neither fixes bug nor adds feature # test: Adding missing tests or correcting existing tests # chore: Changes to build process or auxiliary tools # Examples: feat(auth): add JWT token authentication fix(api): resolve null pointer in user endpoint docs: update installation guide style: format code with prettier refactor: extract database connection logic test: add unit tests for user service chore: update dependencies
Repository Management
# .gitignore patterns # Dependencies node_modules/ vendor/ *.gem # Build outputs dist/ build/ *.jar *.war # Environment files .env .env.local .env.production # IDE files .vscode/ .idea/ *.swp *.swo # OS files .DS_Store Thumbs.db # Logs *.log logs/ # Temporary files *.tmp *.temp
Advanced Git Features
Bisect for Bug Hunting
# Find the commit that introduced a bug git bisect start git bisect bad # Current commit is bad git bisect good v1.0.0 # This commit was good # Git will checkout middle commit, you test it: git bisect good # If this commit is good git bisect bad # If this commit is bad # Continue until bug is found git bisect reset # Return to original state
Worktrees
# Multiple working directories from same repository git worktree add ../feature-branch feature/new-feature cd ../feature-branch # Work on feature independently # List worktrees git worktree list # Remove worktree git worktree remove ../feature-branch
Submodules
# Add submodule git submodule add https://github.com/user/library.git libs/library # Clone repository with submodules git clone --recurse-submodules https://github.com/user/repo.git # Update submodules git submodule update --init --recursive # Working with submodules cd libs/library git checkout main git pull origin main cd ../.. git add libs/library git commit -m "Update submodule to latest version"
Git Security
Security Best Practices
# Signed commits git config --global user.signingkey YOUR_GPG_KEY_ID git commit -S -m "Signed commit" # Verified commits on GitHub # Requires GPG key setup in GitHub settings # Branch protection rules # In repository settings, protect main branch: # - Require pull request reviews # - Require status checks to pass # - Include administrators # - Restrict who can push # Secret scanning # Use pre-commit hooks or GitHub secret scanning # to prevent committing secrets
Troubleshooting Common Issues
Common Problems and Solutions
# Recovering lost commits git reflog # Show reference log git checkout commit-hash # Checkout lost commit git branch recovery-branch # Create branch at recovered commit # Large file issues git filter-branch --tree-filter 'rm -f large-file.zip' HEAD # Or use BFG Repo-Cleaner bfg --delete-files large-file.zip # Permission issues git config --global --unset credential.helper git config --global credential.helper 'cache --timeout=3600' # Merge conflicts git status # See conflicted files # Edit files to resolve conflicts git add . # Mark as resolved git commit # Complete merge
Git with Different Workflows
Feature Branch Workflow
# Complete feature development cycle git checkout -b feature/user-dashboard # ... develop feature ... git add . git commit -m "feat: add user dashboard component" git push -u origin feature/user-dashboard # Create Pull Request on GitHub/GitLab # After review and approval: git checkout main git pull origin main git merge --no-ff feature/user-dashboard git push origin main git branch -d feature/user-dashboard git push origin --delete feature/user-dashboard
Release Process
# Creating releases with semantic versioning git checkout -b release/v1.2.0 # Update version numbers, changelog git commit -m "chore: release v1.2.0" git tag v1.2.0 git push origin release/v1.2.0 git push origin v1.2.0 # Merge to main git checkout main git merge --no-ff release/v1.2.0 git branch -d release/v1.2.0
Conclusion
Git is an essential tool for modern software development that enables efficient collaboration, version control, and code management. Mastering Git not only improves individual productivity but also enhances team collaboration and code quality.
Key Takeaways:
- Understand Git's distributed architecture and core concepts
- Master branching strategies that fit your team's workflow
- Use Git hooks to automate quality checks and enforce standards
- Follow commit message conventions for better history readability
- Implement proper security practices and branch protection
- Leverage Git in CI/CD pipelines for automated testing and deployment
By adopting Git best practices and continuously learning advanced features, development teams can work more efficiently, maintain cleaner codebases, and deliver higher quality software.
Comments
Post a Comment