Menu

Git Topic

Undoing Changes and Fixing Mistakes

What You'll Learn:

  • How to safely undo changes at different stages

  • Fixing commit mistakes without losing work

  • Recovering "lost" commits and changes

Detailed Explanation:

Understanding the Different Levels of Undo

1. Discard Unstaged Changes

# Discard changes in specific file
git checkout -- filename.txt

# Discard all unstaged changes
git checkout -- .

# Using restore (newer command)
git restore filename.txt
git restore .

2. Unstage Files (Keep Changes)

# Unstage specific file
git reset HEAD filename.txt

# Unstage all files
git reset HEAD

# Using restore to unstage
git restore --staged filename.txt

Reset Commands - The Three Modes

Soft Reset (--soft)

# Moves HEAD but keeps changes staged
git reset --soft HEAD~1
# Use case: Recommit with different message or additional changes

Mixed Reset (--mixed) - DEFAULT

# Moves HEAD, unstages changes but keeps in working directory
git reset HEAD~1
git reset --mixed HEAD~1
# Use case: Split a large commit into smaller ones

Hard Reset (--hard)

# COMPLETELY discards changes - USE CAREFULLY!
git reset --hard HEAD~1
git reset --hard commit-hash
# Use case: Completely remove recent commits

Revert vs Reset

Revert (Safe for shared history)

# Creates new commit that undoes changes
git revert commit-hash
git revert HEAD~3..HEAD  # Revert range of commits

# Example workflow:
git log --oneline
# a1b2c3d (HEAD -> main) Bad commit
# e4f5g6h Good commit

git revert a1b2c3d  # Creates new commit undoing a1b2c3d

Reset (Dangerous for shared history)

# Only for local branches - rewrites history
git reset --hard a1b2c3d

Amending Commits

Fix Last Commit Message

git commit --amend -m "New commit message"

Add Files to Last Commit

git add forgotten-file.txt
git commit --amend --no-edit

Change Last Commit Content

# Make changes to files
git add .
git commit --amend
# Opens editor to modify commit message if desired

Reflog - Your Safety Net

View Reflog

git reflog
git reflog show --all
# Shows all HEAD movements - even "lost" commits

Recovery Examples

# Scenario 1: Accidentally reset hard
git reset --hard HEAD~3  # Oops!
git reflog
# Find the commit hash before reset
git reset --hard a1b2c3d  # Restore

# Scenario 2: Deleted branch
git branch -D feature-branch  # Oops!
git reflog
# Find last commit on deleted branch
git checkout -b feature-branch a1b2c3d

# Scenario 3: Lost commit after rebase
git reflog
git cherry-pick a1b2c3d  # Reapply specific commit

Practical Recovery Workflow

# 1. Check what happened
git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# e4f5g6h HEAD@{1}: commit: Important feature

# 2. Restore to desired state
git reset --hard e4f5g6h

# 3. Verify recovery
git log --oneline

Merge Conflicts Resolution

What You'll Learn:

  • What causes merge conflicts and how to prevent them

  • Step-by-step conflict resolution

  • Tools and strategies for efficient resolution

Detailed Explanation:

Understanding Conflict Causes

Common Conflict Scenarios:

  1. Same file, same lines modified by different branches

  2. File deleted in one branch, modified in another

  3. Divergent histories after force pushes

Conflict Resolution Process

1. Identify Conflicted Files

# During merge/pull/rebase, Git will stop and show:
# CONFLICT (content): Merge conflict in filename.txt
# Automatic merge failed; fix conflicts and then commit the result.

git status
# Shows: "Unmerged paths: both modified: filename.txt"

2. Understand Conflict Markers

# In conflicted file:
<<<<<<< HEAD
# Your changes (current branch)
print("Hello from main branch")
=======
# Their changes (incoming branch)
print("Hello from feature branch")
>>>>>>> feature-branch

3. Resolve Conflicts Manually

Option 1: Choose One Version

# Delete conflict markers and keep desired code
print("Hello from main branch")  # Keep your changes
# OR
print("Hello from feature branch")  # Keep their changes

Option 2: Combine Changes

# Create a hybrid solution
print("Hello from main and feature branches")

4. Complete the Resolution

# Mark file as resolved
git add filename.txt

# Complete the operation
git commit  # For merge conflicts
git rebase --continue  # For rebase conflicts

Resolution Strategies

Abort Operations

# Change your mind? Abort the operation:
git merge --abort
git rebase --abort
git cherry-pick --abort

Using Merge Tools

# Configure and use visual merge tools
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

# Use the tool
git mergetool

Advanced Resolution Techniques

Accept All Incoming/Current Changes

# Accept all their changes
git checkout --theirs -- path/to/file
git add path/to/file

# Accept all our changes
git checkout --ours -- path/to/file
git add path/to/file

Partial File Resolution

# Use patch mode for complex files
git add -p filename.txt
# Interactively choose which hunks to stage

Prevention Strategies

1. Frequent Integration

# Keep feature branches short-lived
git fetch origin
git merge origin/main  # Regularly merge main into feature

2. Communication

  • Coordinate with team on file ownership

  • Use pull requests for code review

3. Configuration

# Set up diff3 style for better conflict markers
git config --global merge.conflictstyle diff3

Complete Resolution Example

# Start merge
git merge feature-branch
# CONFLICT occurs

# Identify conflicts
git status

# Edit conflicted files
code conflicted-file.js

# After resolving, mark as resolved
git add conflicted-file.js

# Complete merge
git commit -m "Merge feature-branch, resolve conflicts"

GitHub/GitLab Specific Features

What You'll Learn:

  • Platform-specific collaboration features

  • Managing projects through web interfaces

  • CI/CD integration basics

Detailed Explanation:

Pull/Merge Requests

Creating Effective PRs/MRs:

1. Pre-requisites:

# Local preparation
git checkout -b feature/awesome-feature
# Make changes...
git add .
git commit -m "Implement awesome feature"
git push -u origin feature/awesome-feature

2. PR/MR Best Practices:

  • Title: Clear, descriptive (e.g., "Add user authentication")

  • Description: What, why, how, testing done

  • Linked Issues: Closes #123, Fixes #456

  • Reviewers: Tag relevant team members

3. Template Example:

## Description
What does this PR accomplish?

## Changes
- Change 1
- Change 2

## Testing
- [ ] Unit tests added
- [ ] Manual testing performed

## Screenshots (if UI changes)

Issues and Projects

Effective Issue Management:

Issue Templates:

### Bug Report
**Description**: [What happened]
**Steps to Reproduce**: [Detailed steps]
**Expected Behavior**: [What should happen]
**Actual Behavior**: [What actually happened]

### Feature Request
**Problem**: [What problem this solves]
**Solution**: [Proposed solution]
**Alternatives**: [Other options considered]

Project Boards:

  • Columns: Backlog, In Progress, Review, Done

  • Automation: Auto-move issues based on PRs

  • Milestones: Group related issues for releases

CI/CD Integration

Basic GitHub Actions Workflow (.github/workflows/ci.yml):

name: CI Pipeline
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
    - name: Install dependencies
      run: npm ci
    - name: Run tests
      run: npm test
    - name: Build project
      run: npm run build

GitLab CI (.gitlab-ci.yml):

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - npm install
    - npm test

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

Advanced Platform Features

1. Protected Branches:

  • Require PR reviews

  • Require status checks

  • Prevent force pushes to main

2. Webhooks and Automation:

  • Auto-close issues with PR merges

  • Notifications to Slack/Discord

  • Deployment triggers

3. Code Review Tools:

  • Inline comments

  • Suggested changes

  • Review approvals

Complete Collaboration Workflow

# 1. Create feature branch
git checkout -b feature/new-login

# 2. Develop and commit
git add .
git commit -m "Add new login component"
git push origin feature/new-login

# 3. Create PR/MR on GitHub/GitLab
# - Add description
# - Request reviews
# - Link issues

# 4. Address review feedback
git commit --amend  # Incorporate feedback
git push --force-with-lease

# 5. After approval and merge
git checkout main
git pull origin main
git branch -d feature/new-login

Advanced Git Techniques

What You'll Learn:

  • When to use rebase vs merge

  • Advanced history rewriting

  • Managing complex project dependencies

Detailed Explanation:

Rebasing vs Merging

Merge - Preserves History

# Creates merge commit showing branch integration
git checkout main
git merge feature-branch

# Result:
# *   Merge branch 'feature-branch'
# |\  
# | * Feature commit 2
# | * Feature commit 1
# |/  
# * Main commit

Rebase - Linear History

# Replays commits on top of base branch
git checkout feature-branch
git rebase main

# Result:
# * Feature commit 2
# * Feature commit 1
# * Main commit

When to Use Each:

Scenario Use Merge Use Rebase
Public/shared branches ✅ ❌
Feature branches ✅ ✅
Cleaning up local history ❌ ✅
Team prefers clear merge points ✅ ❌

Interactive Rebase

Basic Usage:

# Rebase last 3 commits
git rebase -i HEAD~3

# Rebase onto different branch
git rebase -i main

Interactive Rebase Actions:

pick a1b2c3d Add feature A
reword e4f5g6h Fix typo
edit f7g8h9i Add tests
squash j1k2l3m More tests
drop m4n5o6p Debug code

Common Scenarios:

1. Squash Multiple Commits:

git rebase -i HEAD~4
# Change "pick" to "squash" for commits to combine

2. Reorder Commits:

git rebase -i HEAD~5
# Reorder lines to change commit sequence

3. Split Large Commit:

git rebase -i HEAD~2
# Mark commit as "edit"
# During rebase:
git reset HEAD~1
# Stage changes in separate commits
git add -p
git commit -m "Part 1"
git commit -m "Part 2"
git rebase --continue

Submodules and Worktrees

Git Submodules - Nested Repositories

# Add submodule
git submodule add https://github.com/user/repo.git lib/repo

# Clone repository with submodules
git clone --recurse-submodules https://github.com/user/main-repo.git

# Update submodules
git submodule update --init --recursive

# Work in submodule
cd lib/repo
git checkout -b feature
# Make changes...
cd ../..
git add lib/repo
git commit -m "Update submodule"

Git Worktrees - Multiple Working Directories

# Create new worktree for feature branch
git worktree add ../my-project-feature feature-branch

# Work in parallel
cd ../my-project-feature
# Make changes...
git commit -m "Feature work"

# List worktrees
git worktree list

# Remove worktree
git worktree remove ../my-project-feature

Advanced Cherry-picking

Selective Commit Application:

# Cherry-pick specific commit
git cherry-pick a1b2c3d

# Cherry-pick range
git cherry-pick main..feature-branch

# Cherry-pick with conflicts
git cherry-pick --continue
git cherry-pick --abort

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

Bisect for Bug Hunting

Find Introducing Commit:

# Start bisect session
git bisect start
git bisect bad HEAD          # Current commit is bad
git bisect good v1.0.0       # This commit was good

# Test current commit, then:
git bisect good              # If current commit is good
git bisect bad               # If current commit is bad

# Finish bisect
git bisect reset

Git in Team Environments

What You'll Learn:

  • Establishing effective team workflows

  • Code review best practices

  • Release and deployment management

Detailed Explanation:

Code Review Workflows

1. Fork & Pull Request Workflow:

# Contributor workflow:
# 1. Fork on GitHub/GitLab
# 2. Clone fork
git clone https://github.com/yourname/repo.git
# 3. Add upstream
git remote add upstream https://github.com/original/repo.git
# 4. Create feature branch
git checkout -b feature-branch
# 5. Push to fork
git push -u origin feature-branch
# 6. Create PR from fork to upstream

2. Shared Repository Workflow:

# Team member workflow:
# 1. Clone main repo
git clone https://github.com/team/repo.git
# 2. Create feature branch
git checkout -b feature/description
# 3. Push to origin
git push -u origin feature/description
# 4. Create PR within same repo

Code Review Best Practices:

Before Review:

  • Self-review your code

  • Ensure tests pass

  • Update documentation

  • Keep PRs focused and small

During Review:

  • Use inline comments

  • Suggest changes (GitHub)

  • Request specific reviewers

  • Discuss, don't dictate

Review Checklist:

  • Code follows team standards

  • Tests added/updated

  • Documentation updated

  • Security considerations

  • Performance impact assessed

Branch Protection Rules

Essential Protections for Main Branch:

  • Require pull requests

  • Require approvals (1-2 reviewers)

  • Require status checks (CI passing)

  • Prevent force pushes

  • Require linear history

GitHub Example:

# .github/branch-protection.yml
main:
  required_status_checks:
    strict: true
    contexts: [ci/tests, ci/build]
  required_pull_request_reviews:
    required_approving_review_count: 2
    dismiss_stale_reviews: true
  enforce_admins: false
  restrictions: null

Release Management

Semantic Versioning Strategy:

# Create release branches
git checkout -b release/v1.2.0
# Final testing, bug fixes
git tag v1.2.0
git push origin v1.2.0

# Hotfix workflow
git checkout -b hotfix/v1.2.1 main
# Fix critical issue
git tag v1.2.1
git push origin v1.2.1

Automated Versioning:

# Using semantic-release or similar
npm version patch  # 1.2.3 → 1.2.4
npm version minor  # 1.2.3 → 1.3.0  
npm version major  # 1.2.3 → 2.0.0

git push --follow-tags

Team Coordination Strategies

1. Regular Syncs:

# Daily: Fetch latest changes
git fetch --all

# Weekly: Clean up merged branches
git fetch -p  # Prune deleted remote branches
git branch --merged main | grep -v "main" | xargs git branch -d

2. Communication Protocols:

  • Use conventional commits

  • Document breaking changes

  • Announce large refactors

  • Coordinate database changes

3. Conflict Prevention:

# Pre-merge checks
git fetch origin
git merge-base --fork-point origin/main feature-branch
# Ensure feature branch isn't too far behind

Large Team Scale Strategies

Monorepo Management:

# Sparse checkout for large repos
git sparse-checkout init
git sparse-checkout set app/frontend

# Partial clones
git clone --filter=blob:none https://github.com/large/repo.git

Team-specific Branches:

# Team feature flags
git checkout -b team/frontend/feature-name
git checkout -b team/backend/feature-name

Git Hooks and Automation

What You'll Learn:

  • Automating workflows with Git hooks

  • Integrating with CI/CD systems

  • Creating custom Git commands

Detailed Explanation:

Pre-commit Hooks

Location and Setup:

# Hooks live in .git/hooks/
# But better: store in project and use a hook manager

# Using Husky (Node.js projects)
npm install husky --save-dev
npx husky init

# Add pre-commit hook
npx husky add .husky/pre-commit "npm test"

Common Pre-commit Validations:

1. Code Quality:

#!/bin/bash
# .husky/pre-commit

# Run linter
npm run lint

# Run tests
npm test

# Check commit message format
commit_msg=$(cat $1)
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore): "; then
  echo "Invalid commit message format!"
  exit 1
fi

2. Security Checks:

#!/bin/bash
# Check for secrets in code
if git diff --cached --name-only | xargs grep -n "password\|secret\|key"; then
  echo "Potential secret found in code!"
  exit 1
fi

CI Integration Hooks

Post-receive Hook for Auto-deploy:

#!/bin/bash
# .git/hooks/post-receive

while read oldrev newrev refname
do
  branch=$(git rev-parse --symbolic --abbrev-ref $refname)
  if [ "main" == "$branch" ]; then
    # Deploy to production
    git --work-tree=/var/www/html --git-dir=/path/to/repo checkout -f
    systemctl reload nginx
  fi
done

Pre-push Hook for Validation:

#!/bin/bash
# .husky/pre-push

# Ensure tests pass before push
npm run test:ci

# Check branch naming convention
current_branch=$(git symbolic-ref --short HEAD)
if ! echo "$current_branch" | grep -qE "^(feature|fix|hotfix)/[a-z0-9-]+$"; then
  echo "Invalid branch name: $current_branch"
  exit 1
fi

Custom Git Commands

Creating Git Aliases:

# Add to ~/.gitconfig or project .git/config

[alias]
  # Shortcuts
  co = checkout
  br = branch
  ci = commit
  st = status
  
  # Useful custom commands
  last = log -1 HEAD
  unstage = reset HEAD --
  recent = log --oneline -10
  graph = log --graph --oneline --all
  
  # Team-specific aliases
  cleanup = "!git fetch -p && git branch --merged main | grep -v main | xargs git branch -d"
  wip = "!git add -A && git commit -m 'WIP'"
  unwip = "!git reset --soft HEAD~1"

Advanced Custom Commands:

1. Branch Cleanup Script:

#!/bin/bash
# Save as git-cleanup-branches

# Delete merged branches except main and develop
git fetch --prune
git branch --merged main | grep -vE "^(main|develop|\*)" | xargs -r git branch -d
git branch --merged develop | grep -vE "^(main|develop|\*)" | xargs -r git branch -d
echo "Cleanup complete!"

2. Smart Commit:

#!/bin/bash
# git-smart-commit

if [ -z "$1" ]; then
  echo "Usage: git smart-commit \"message\""
  exit 1
fi

# Run tests first
npm test

if [ $? -eq 0 ]; then
  git add -A
  git commit -m "$1"
  echo "Commit successful!"
else
  echo "Tests failed! Commit aborted."
  exit 1
fi

Hook Management Tools

1. Husky (Node.js):

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.js": "eslint --fix",
    "*.{js,css,md}": "prettier --write"
  }
}

2. pre-commit (Python):

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.4.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml

Complete Automation Example

Project Setup with Full Automation:

#!/bin/bash
# setup-project.sh

# Initialize project
npm init -y
npm install husky lint-staged @commitlint/cli @commitlint/config-conventional

# Configure Git hooks
npx husky init
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
npx husky add .husky/pre-commit 'npx lint-staged'

# Create configuration files
cat > .commitlintrc.json << EOF
{
  "extends": ["@commitlint/config-conventional"]
}
EOF

cat > .lintstagedrc.json << EOF
{
  "*.js": ["eslint --fix", "prettier --write"],
  "*.json": ["prettier --write"],
  "*.md": ["prettier --write"]
}
EOF

echo "Project automation setup complete!"

This completes the extensive Git tutorial covering from basic to advanced topics. Each subtopic builds upon the previous ones, creating a logical learning path for mastering Git.

 

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?