๐ Advanced Techniques โ
git stash โ Temporarily Save Your Work โ
Scenario: You're developing a new feature when your boss suddenly says "There's an urgent bug in production, fix it now!" Your code is half-done and you don't want to commit an unfinished change. What do you do? git stash to the rescue!
# "Hide" your current changes
git stash
Saved working directory and index state WIP on main: f4e5d6c feat: add welcome message
# Working directory is now clean
git status
On branch main
nothing to commit, working tree clean
# Now you can fix the bug with peace of mind...
# After fixing and committing the bug, restore your work
git stash pop
On branch main
Changes not staged for commit:
modified: index.html
# View all stash records
git stash list
stash@{0}: WIP on main: f4e5d6c feat: add welcome message
# Stash with a description (recommended!)
git stash push -m "working on user avatar feature"
git stash list
stash@{0}: On main: working on user avatar feature
# Restore a specific stash (don't delete the stash record)
git stash apply stash@{0}
# Restore and delete the stash record
git stash pop stash@{0}
# Delete all stashes
git stash cleargit cherry-pick โ Precisely "Transplant" a Commit โ
Sometimes you want to "move" just one specific commit to another branch, rather than merging the entire branch. This is where cherry-pick comes in as a powerful tool.
# Scenario: The feature/experiment branch has an urgent fix, you want to move just that to main
# First find the commit hash
git log --oneline feature/experiment
d4e5f6a feat: experimental feature A
c3d4e5f fix: fixed a critical bug
b2c3d4e feat: experimental feature B
a1b2c3d feat: initialize experiment branch
# Switch to main and cherry-pick that fix
git switch main
git cherry-pick c3d4e5f
[main e5f6a7b] fix: fixed a critical bug
Date: Thu Jun 20 15:30:00 2025 +0800
1 file changed, 2 insertions(+), 1 deletion(-)
# You can also cherry-pick multiple commits at once
git cherry-pick a1b2c3d..c3d4e5f
# Cherry-pick without auto-committing (lets you review first)
git cherry-pick --no-commit c3d4e5fgit bisect โ Binary Search for Bug Hunting โ
This command is amazing! If you know the code was working 100 commits ago and there's a bug now, bisect uses binary search to quickly pinpoint which commit introduced the bug.
# Start binary search
git bisect start
# Mark the current version as buggy
git bisect bad
# Mark an older version as good
git bisect good a1b2c3d
Bisecting: 50 revisions left to test after this (roughly 6 steps)
[f5a6b7c...] feat: add search feature
# Git automatically checks out the middle commit
# Test this version...
# If it's good:
git bisect good
Bisecting: 25 revisions left to test after this (roughly 5 steps)
# If it's buggy:
git bisect bad
Bisecting: 12 revisions left to test after this (roughly 4 steps)
# After a few rounds, Git will tell you:
a7b8c9d is the first bad commit
commit a7b8c9d
Author: Bob <bob@example.com>
Date: Thu Jun 20 14:00:00 2025 +0800
feat: add shopping cart feature
:040000 040000 abc123 def456 M cart.js
# Found the "culprit"! End bisect
git bisect resetgit blame โ Who Wrote This Line of Code? โ
# View the last modifier of each line in a file
git blame index.html
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 1) <!DOCTYPE html>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 2) <html>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 3) <head>
f4e5d6c7 (Alice 2025-06-20 10:30:00 +0800 4) <title>My First Website</title>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 5) </head>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 6) <body>
d4e5f6a7 (Bob 2025-06-20 11:00:00 +0800 7) <h1>Welcome to our website!</h1>
f4e5d6c7 (Alice 2025-06-20 10:30:00 +0800 8) <p>Hello, Git!</p>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 9) </body>
a1b2c3d4 (Alice 2025-06-20 10:00:00 +0800 10) </html>
# View a specific line range
git blame -L 5,8 index.htmlgit grep โ Search Within Code โ
# Search code content (faster than grep because it uses Git's index)
git grep "Hello"
index.html:7: <h1>Hello, Git!</h1>
# Search and count matches per file
git grep -c "class"
index.html:2
style.css:5
# Search content in a specific commit
git grep "Hello" a1b2c3dGit Aliases โ Nicknames for Commands โ
Some Git commands are too long and tedious to type. Setting up aliases doubles your efficiency:
# Common alias settings
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 --oneline --graph --all --decorate"
git config --global alias.last "log -1 HEAD"
git config --global alias.unstage "restore --staged"
git config --global alias.aliases "config --get-regexp alias"
# Using aliases
git st # = git status
git co main # = git checkout main
git lg # = nice commit historyGit Hooks โ Automation Scripts โ
Git Hooks are scripts that automatically execute when specific events occur. For example, automatically checking code format before each commit, or running tests before each push.
# View available hooks
ls .git/hooks/
applypatch-msg.sample pre-commit.sample pre-rebase.sample
commit-msg.sample pre-merge-commit.sample prepare-commit-msg.sample
fsmonitor-watchman.sample pre-push.sample update.sample
# Create a pre-commit hook (run checks before committing)
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# Check for unresolved conflict markers
if git diff --cached --diff-filter=ACM | grep -q '<<<<<<'; then
echo "Error: Found unresolved conflict markers! Please resolve conflicts first."
exit 1
fi
# Check for debug statements
if git diff --cached --diff-filter=ACM | grep -qE 'console\.log|debugger|print\('; then
echo "Warning: Code may contain debug statements."
echo "If intentional, use git commit --no-verify to skip checks."
exit 1
fi
EOF
# Make it executable
chmod +x .git/hooks/pre-commit๐ Note: Scripts in
.git/hooks/won't be committed to the repository. If you want to share hooks with your team, you can use thepre-committool, or place hook scripts in the project directory and use symlinks.
Git Submodules โ A Repository Within a Repository โ
Sometimes your project depends on another Git repository (like a shared utility library). submodule lets you nest one repository inside another.
# Add a submodule
git submodule add git@github.com:yourname/shared-utils.git libs/utils
Cloning into '/home/yourname/my-first-website/libs/utils'...
remote: Enumerating objects: 42, done.
...
Adding existing repo at 'libs/utils' to the index
# View submodule status
git submodule status
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 libs/utils (heads/main)
# Clone a repository with submodules
git clone --recurse-submodules git@github.com:yourname/my-first-website.git
# If you already cloned but forgot --recurse-submodules
git submodule update --init --recursive