Git Advanced Operations
This chapter introduces advanced Git features and techniques, including rebase, stash, submodule, hooks, and more, helping you use Git more efficiently.
Git Rebase Explained
What is Rebase?
Rebase is the operation of reapplying a series of commits on top of another base commit. It can create a cleaner project history.
Before Rebase:
A---B---C (main)
\
D---E (feature)
After Rebase:
A---B---C---D'---E' (feature)Basic Rebase Operations
# Rebase current branch onto main
git rebase main
# Rebase feature branch onto main
git rebase main feature
# Interactive rebase
git rebase -i HEAD~3
# Continue rebase (after resolving conflicts)
git rebase --continue
# Skip current commit
git rebase --skip
# Abort rebase
git rebase --abortDemonstrating Rebase Operations
# Create demo environment
mkdir git-rebase-demo
cd git-rebase-demo
git init
# Create commits on main branch
echo "Main branch file 1" > main1.txt
git add main1.txt
git commit -m "Main commit 1"
echo "Main branch file 2" > main2.txt
git add main2.txt
git commit -m "Main commit 2"
# Create feature branch
git checkout -b feature
echo "Feature file 1" > feature1.txt
git add feature1.txt
git commit -m "Feature commit 1"
echo "Feature file 2" > feature2.txt
git add feature2.txt
git commit -m "Feature commit 2"
# Add new commit on main branch
git checkout main
echo "Main branch file 3" > main3.txt
git add main3.txt
git commit -m "Main commit 3"
# Rebase feature branch onto latest main branch
git checkout feature
git rebase main
# View history
git log --oneline --graphInteractive Rebase
Interactive rebase allows you to modify commit history:
# Start interactive rebase
git rebase -i HEAD~3You can perform the following operations in the editor:
pick: Use commitreword: Edit commit messageedit: Use commit, but stop for amendingsquash: Use commit, but meld into previous commitfixup: Like "squash", but discard this commit's log messagedrop: Remove commit
# Example: Squash last 3 commits
git rebase -i HEAD~3
# Modify in editor:
pick abc1234 First commit
squash def5678 Second commit
squash ghi9012 Third commitRebase vs Merge
# Merge preserves branch history
git checkout main
git merge feature
# Rebase creates linear history
git checkout feature
git rebase main
git checkout main
git merge feature # This will be a fast-forward mergeGit Stash Explained
What is Stash?
Stash allows you to temporarily save changes in your working directory and staging area, so you can quickly switch branches or pull updates.
Basic Stash Operations
# Save current changes
git stash
# Save with description
git stash push -m "Temporarily save login feature"
# View stash list
git stash list
# Apply latest stash
git stash pop
# Apply specific stash
git stash apply stash@{1}
# Drop stash
git stash drop stash@{0}
# Clear all stashes
git stash clearDemonstrating Stash Operations
# Make some changes
echo "Feature in progress" > work_in_progress.txt
echo "Modifying existing file" >> existing_file.txt
# Add to staging area
git add work_in_progress.txt
# Save to stash
git stash push -m "Save feature in progress"
# View stash
git stash list
# Switch branch to handle urgent issue
git checkout -b hotfix
echo "Urgent fix" > hotfix.txt
git add hotfix.txt
git commit -m "Urgent fix"
# Return to original branch and restore work
git checkout main
git stash pop
# Continue development
git add .
git commit -m "Complete feature development"Advanced Stash Operations
# Stash only working directory changes, keep index (staging area)
git stash --keep-index
# Include untracked files
git stash -u
# Include ignored files
git stash -a
# Interactive stash
git stash -p
# Create branch from stash
git stash branch new-feature stash@{0}
# View stash content
git stash show stash@{0}
git stash show -p stash@{0} # Show detailed diffGit Submodule
What is Submodule?
Submodule allows you to keep a Git repository as a subdirectory of another Git repository.
Adding Submodule
# Add submodule
git submodule add https://github.com/user/repo.git path/to/submodule
# Add submodule from specific branch
git submodule add -b branch-name https://github.com/user/repo.git path/to/submodule
# Commit submodule configuration
git add .gitmodules path/to/submodule
git commit -m "Add submodule"Cloning Repository with Submodules
# Clone main repository
git clone https://github.com/user/main-repo.git
# Initialize and update submodule
git submodule init
git submodule update
# Or do it all at once
git clone --recursive https://github.com/user/main-repo.git
# Or after cloning
git submodule update --init --recursiveUpdating Submodule
# Enter submodule directory to update
cd path/to/submodule
git pull origin main
# Update submodule in main repository
git submodule update --remote
# Update specific submodule
git submodule update --remote path/to/submodule
# Commit submodule update
git add path/to/submodule
git commit -m "Update submodule"Demonstrating Submodule Operations
# Create main project
mkdir main-project
cd main-project
git init
# Create a sub-project (simulate external library)
mkdir ../library
cd ../library
git init
echo "Library functions" > lib.js
git add lib.js
git commit -m "Initial library commit"
# Return to main project, add submodule
cd ../main-project
git submodule add ../library lib
# View status
git status
cat .gitmodules
# Commit submodule configuration
git add .
git commit -m "Add library as submodule"
# Make changes in submodule
cd lib
echo "New feature" >> lib.js
git add lib.js
git commit -m "Add new feature"
# Update submodule reference in main project
cd ..
git add lib
git commit -m "Update library to latest version"Git Hooks
What are Hooks?
Hooks are scripts that are automatically executed when specific Git events occur.
Common Hooks
# Client-side hooks (in .git/hooks/ directory)
pre-commit # Executed before commit
prepare-commit-msg # Executed when preparing commit message
commit-msg # Executed to validate commit message
post-commit # Executed after commit
pre-push # Executed before push
# Server-side hooks
pre-receive # Executed before receiving push
update # Executed when updating references
post-receive # Executed after receiving pushCreating Pre-commit Hook
# Create pre-commit hook
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# Check code style
echo "Checking code style..."
# Check JavaScript files
js_files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -n "$js_files" ]; then
echo "Checking JavaScript files: $js_files"
# Can add ESLint check here
# eslint $js_files
fi
# Check Python files
py_files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
if [ -n "$py_files" ]; then
echo "Checking Python files: $py_files"
# Can add flake8 check here
# flake8 $py_files
fi
# Check if commit contains debug code
if git diff --cached | grep -E "(console\.log|debugger|pdb\.set_trace)"; then
echo "Error: Commit contains debug code"
exit 1
fi
echo "Code check passed"
exit 0
EOF
# Make script executable
chmod +x .git/hooks/pre-commitCreating Commit-msg Hook
# Create commit-msg hook to validate commit message format
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash
commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}'
if ! grep -qE "$commit_regex" "$1"; then
echo "Invalid commit message format!"
echo "Format should be: type(scope): description"
echo "Types: feat, fix, docs, style, refactor, test, chore"
echo "Example: feat(auth): Add user login function"
exit 1
fi
EOF
chmod +x .git/hooks/commit-msgDemonstrating Hooks Usage
# Test pre-commit hook
echo "console.log('debug');" > debug.js
git add debug.js
git commit -m "Add debug code" # Should be blocked
# Remove debug code
echo "function hello() { return 'Hello World'; }" > debug.js
git add debug.js
git commit -m "feat: Add hello function" # Should succeed
# Test invalid commit message format
git commit --allow-empty -m "Wrong format" # Should be blocked
# Correct commit message format
git commit --allow-empty -m "docs: Update README" # Should succeedGit Worktree
What is Worktree?
Worktree allows you to check out multiple branches of the same repository into different directories simultaneously.
Worktree Operations
# Create new worktree
git worktree add ../feature-branch feature-branch
# Create worktree for new branch
git worktree add -b new-feature ../new-feature
# List all worktrees
git worktree list
# Remove worktree
git worktree remove ../feature-branch
# Prune invalid worktrees
git worktree pruneDemonstrating Worktree Usage
# Work in main directory
pwd # /path/to/main-project
# Create worktree for feature branch
git worktree add ../feature-work feature-branch
# Now can work in two directories simultaneously
cd ../feature-work
# Develop feature branch here
# Return to main directory
cd ../main-project
# Handle main branch work here
# View all worktrees
git worktree listGit Bisect
What is Bisect?
Bisect uses binary search to help you find the commit that introduced a bug.
Bisect Operations
# Start bisect
git bisect start
# Mark current commit as bad
git bisect bad
# Mark known good commit
git bisect good commit_hash
# Git will automatically switch to the middle commit
# Mark result after testing
git bisect good # or git bisect bad
# Continue until problem commit is found
# End bisect
git bisect resetAutomating Bisect
# Use script to automate testing
git bisect start HEAD v1.0
git bisect run ./test_script.sh
# Example test_script.sh
#!/bin/bash
make test
exit $? # Return 0 means good, non-0 means badGit Filter-branch and Filter-repo
Rewriting History
# Remove file from history (using filter-branch)
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# Using git-filter-repo (Recommended)
pip install git-filter-repo
git filter-repo --path passwords.txt --invert-paths
# Rewrite author information
git filter-repo --mailmap mailmap.txt
# mailmap.txt format:
# New Name <new@email.com> Old Name <old@email.com>Advanced Configuration and Aliases
Useful Git Aliases
# Set advanced aliases
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
# Complex aliases
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'
# Find alias
git config --global alias.find '!git ls-files | xargs grep -l'
# Count alias
git config --global alias.count 'shortlog -sn'
# Cleanup alias
git config --global alias.cleanup '!git branch --merged | grep -v "\\*\\|main\\|master" | xargs -n 1 git branch -d'Advanced Configuration
# Set default editor
git config --global core.editor "code --wait"
# Set diff tool
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
# Set merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Auto-correct typos
git config --global help.autocorrect 1
# Set push policy
git config --global push.default simple
# Enable rerere (reuse recorded resolution)
git config --global rerere.enabled true
# Set long path support (Windows)
git config --global core.longpaths truePerformance Optimization
Large Repository Optimization
# Shallow clone
git clone --depth 1 <url>
# Partial clone
git clone --filter=blob:none <url>
# Sparse checkout
git config core.sparseCheckout true
echo "src/" > .git/info/sparse-checkout
git read-tree -m -u HEAD
# Garbage collection
git gc --aggressive --prune=now
# Repack
git repack -ad
# Clean untracked files
git clean -fdNetwork Optimization
# Set proxy
git config --global http.proxy http://proxy.company.com:8080
# Increase buffer size
git config --global http.postBuffer 524288000
# Enable parallel transfer
git config --global http.maxRequestBuffer 100M
git config --global http.threads 5Troubleshooting and Debugging
Git Debugging Tips
# Enable verbose output
GIT_TRACE=1 git status
GIT_TRACE_PACKET=1 git push
GIT_TRACE_PERFORMANCE=1 git log
# Check repository integrity
git fsck --full
# View object info
git cat-file -t commit_hash # View object type
git cat-file -p commit_hash # View object content
# View references
git show-ref
# View config
git config --list --show-originCommon Issues Resolution
# Issue 1: Push rejected
git pull --rebase origin main
git push origin main
# Issue 2: Merge conflict
git status
git mergetool
git commit
# Issue 3: Detached HEAD state
git checkout -b new-branch
git checkout main
git merge new-branch
# Issue 4: File permission issue
git config core.filemode false
# Issue 5: Line ending issue
git config core.autocrlf true # Windows
git config core.autocrlf input # macOS/LinuxSummary
Key points of Git Advanced Operations:
Important Tools
rebase # Rewrite history, create linear commits
stash # Temporarily save changes
submodule # Manage sub-projects
hooks # Automate workflows
worktree # Parallel work on multiple branches
bisect # Binary search for issuesBest Practices
- ✅ Use rebase to maintain clean history
- ✅ Utilize stash to switch tasks flexibly
- ✅ Automate checks via hooks
- ✅ Manage dependencies reasonably with submodule
- ✅ Configure useful aliases to improve efficiency
Performance Optimization
- 🚀 Shallow clone large repositories
- 🚀 Use sparse checkout
- 🚀 Regular garbage collection
- 🚀 Optimize network configuration
After mastering these advanced operations, you will be able to:
- 🔧 Efficiently manage complex project history
- ⚡ Automate common workflows
- 🎯 Quickly locate and resolve issues
- 📈 Optimize Git usage performance
In the next chapter, we will learn Git Best Practices.