Git Advanced Workflows & Conflict Resolution in Practice
Git Workflow Panoramic Comparison
Choosing the right Git workflow is the foundation of team collaboration. Teams of different sizes and release cadences need different branching strategies.
Three Mainstream Workflows
| Workflow | Branch Model | Use Case | Release Cadence |
|---|---|---|---|
| Git Flow | main + develop + feature + release + hotfix | Projects with explicit version numbers | Planned releases (v1.0, v2.0) |
| GitHub Flow | main + feature | Continuously deployed Web/SaaS projects | Continuous release |
| Trunk-Based | main + short-lived feature (<1 day) | Mature CI/CD teams | Continuous integration + Feature Flags |
Git Flow in Detail
Git Flow was proposed by Vincent Driessen and is the most classic branching model:
# Initialize Git Flow (requires git-flow installation)
git flow init
# Start feature development
git flow feature start user-auth
# → Creates feature/user-auth from develop
# Finish feature (auto-merges back to develop and deletes branch)
git flow feature finish user-auth
# Start release preparation
git flow release start v1.2.0
# → Creates release/v1.2.0 from develop
# Finish release (merges to main + develop, tags)
git flow release finish v1.2.0
# Emergency fix
git flow hotfix start critical-bug
# → Creates hotfix/critical-bug from main
git flow hotfix finish critical-bug
# → Merges to main + develop, tags
Branch Lifecycle Diagram:
main: ●────────────────●────────●
\ / /
develop: ●──●──●──●──●──●──●──●──●──●
/ / \ /
feature: ●──●──● release: ●──● hotfix: ●──●
GitHub Flow in Detail
Minimalist model, ideal for continuous deployment:
# 1. Create feature branch from main
git checkout -b feature/add-search main
# 2. Develop and commit
git add . && git commit -m "feat: add search component"
# 3. Push and create PR
git push -u origin feature/add-search
# 4. After Code Review approval, merge to main
# 5. Auto-deploy to production
Trunk-Based Development in Detail
Everyone integrates frequently on main (trunk), using Feature Flags to control incomplete features:
# Short-lived branch (must merge within <1 day)
git checkout -b fix/login-timeout main
git add . && git commit -m "fix: login timeout handling"
git push -u origin fix/login-timeout
# → Merge immediately after CI passes, delete branch
# Feature Flag example (controlled in code)
# if (flags.NEW_SEARCH_ENABLED) {
# return newSearch(query);
# }
# return legacySearch(query);
Workflow Pros & Cons Comparison
| Dimension | Git Flow | GitHub Flow | Trunk-Based |
|---|---|---|---|
| Complexity | High | Low | Medium |
| Parallel Development | Excellent | Good | Excellent (requires Feature Flags) |
| Release Control | Strong | Weak | Medium |
| Conflict Risk | High (long-lived branches) | Low | Lowest |
| Rollback Difficulty | Easy (hotfix branch) | Easy (revert PR) | Needs Feature Flags |
| CI/CD Friendliness | Medium | High | Highest |
| Team Size Fit | 5-50 people | 2-20 people | 10+ mature teams |
💡 Use the Hash Tool to generate commit signatures, ensuring code integrity.
Interactive Rebase Step-by-Step
Interactive Rebase is Git's most powerful history rewriting tool. Mastering it means mastering the "time machine" for commit history.
Basic Syntax
# Interactive rebase of the last 3 commits
git rebase -i HEAD~3
# Interactive rebase after a specific commit
git rebase -i abc1234^
# The editor will show:
# pick f1a2b3c feat: add user model
# pick d4e5f6g fix: validation error
# pick h7i8j9k docs: update README
Squash: Combine Commits
Compress multiple small commits into one meaningful commit:
git rebase -i HEAD~3
# Change to:
# pick f1a2b3c feat: add user model
# squash d4e5f6g fix: validation error
# squash h7i8j9k docs: update README
# → 3 commits combined into 1, edit the combined commit message
Typical scenario: Combine "WIP", "fix typo", "fix again" etc. into a single meaningful record.
Fixup: Silent Combine
Similar to squash, but automatically discards the merged commit's message:
git rebase -i HEAD~3
# pick f1a2b3c feat: add user model
# fixup d4e5f6g fix: validation error
# fixup h7i8j9k fix: another fix
# → Only keeps the first commit's message
Faster approach — mark fixup at commit time:
git commit --fixup=f1a2b3c
# Then auto-rebase in one step:
git rebase -i --autosquash HEAD~3
Reorder: Adjust Commit Order
Simply rearrange lines in the editor:
git rebase -i HEAD~3
# Original order:
# pick f1a2b3c feat: add user model
# pick d4e5f6g feat: add user service
# pick h7i8j9k test: user model test
# Rearranged (test follows model):
# pick f1a2b3c feat: add user model
# pick h7i8j9k test: user model test
# pick d4e5f6g feat: add user service
Edit: Split a Commit
Split an oversized commit into multiple:
git rebase -i HEAD~2
# pick f1a2b3c feat: add user module (too large)
# edit d4e5f6g feat: add auth module
# Git pauses at the edit-marked commit
git reset HEAD~1
# Now all files are back in staging area, commit in batches
git add src/models/user.ts
git commit -m "feat: add user model"
git add src/services/user.ts
git commit -m "feat: add user service"
git rebase --continue
Mid-Rebase Operations
# Continue to the next commit
git rebase --continue
# Skip the current commit
git rebase --skip
# Abort the entire rebase, return to original state
git rebase --abort
⚠️ Golden Rule: Never rebase commits that have been pushed to a remote shared branch! This will corrupt others' history.
Merge vs Rebase Deep Comparison
This is the most classic debate in the Git community. Both have their use cases.
Visual Comparison
Merge — preserves full history, creates a merge commit:
main: ●──●──●──M──●
\ /
feature: ●──●
Rebase — linear history, no merge commit:
main: ●──●──●──●'──●'
↑ feature commits replayed after main
When to Use Merge
# Merge feature branch into main (preserve branch history)
git checkout main
git merge --no-ff feature/user-auth
# --no-ff disables fast-forward merge, ensures merge commit is created
Use cases:
- Merging feature branches into main/develop
- Need to preserve trace of branch existence
- Team requires complete project history
When to Use Rebase
# Sync main updates onto feature branch
git checkout feature/user-auth
git rebase main
# → feature commits are "appended after" main's latest commit
Use cases:
- Syncing upstream branch updates to local feature branch
- Cleaning up local fragmented commits
- Keeping commit history linear and readable
Comparison Summary
| Dimension | Merge | Rebase |
|---|---|---|
| History | Preserves real branch history | Rewrites as linear history |
| Merge Commits | Yes (potentially many) | None |
| Readability | Complex branch graph | Clean linear |
| Safety | Safe (doesn't modify history) | Dangerous (rewrites pushed commits) |
| Conflict Handling | Resolve all at once | Resolve per commit |
| Rollback | git revert -m |
Requires rebase or reset |
| Recommended For | Merging into main branch | Syncing upstream updates |
Practical Recommendation
# Recommended team workflow combination:
# 1. During feature development: use rebase to sync develop
git checkout feature/x
git fetch origin
git rebase origin/develop
# 2. When feature is done: use merge (--no-ff) back to develop
git checkout develop
git merge --no-ff feature/x
# 3. develop to main: use merge (--no-ff)
git checkout main
git merge --no-ff develop
Conflict Resolution Strategies
Conflicts are inevitable in collaborative development. Systematic resolution strategies are far more efficient than "guessing".
3-Way Merge Principle
Git uses the three-way merge algorithm:
Base (common ancestor)
/ \
Ours Theirs
\ /
Merge Result
- Find the common ancestor (Base) of both branches
- Compare Ours vs Base, Theirs vs Base
- Only one side modified → auto-merge
- Both sides modified the same line → conflict, requires manual resolution
# See which files have conflicts
git diff --name-only --diff-filter=U
# See detailed conflict content
git diff
Manual Conflict Resolution
Conflict marker format:
<<<<<<< HEAD
Content from current branch
=======
Content from merging branch
>>>>>>> feature/other-branch
Resolution steps:
# 1. Open conflicted files, edit manually
# 2. Remove conflict markers, keep correct content
# 3. Mark as resolved
git add <conflicted-file>
# 4. Complete the merge
git commit
# Or during rebase:
git rebase --continue
Using Merge Tools
# Use VS Code as merge tool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Use vimdiff
git config --global merge.tool vimdiff
# Launch merge tool
git mergetool
git rerere: Auto-Remember Conflict Resolutions
rerere (Reuse Recorded Resolution) lets Git remember how you resolved similar conflicts, auto-applying next time:
# Enable rerere globally
git config --global rerere.enabled true
# Or enable in a specific repo
cd your-repo
git config rerere.enabled true
How it works:
- First encounter → manual resolution → Git records the solution
- Same conflict again → auto-applies previous solution
- If auto-resolution is wrong →
git rerere forgetto delete the memory
# View recorded conflict resolutions
git rerere status
# Forget the recorded resolution for current conflict
git rerere forget
# Manually trigger replay
git rerere
Typical scenario: Long-lived feature branch repeatedly merged with develop, same conflicts keep appearing.
Conflict Resolution Strategy Selection
| Strategy | Use Case | Command |
|---|---|---|
| Manual Edit | Few conflicts, need careful judgment | Edit files directly |
| Merge Tool | Many conflicts, need visualization | git mergetool |
| Ours Strategy | Always use our version | git merge -X ours |
| Theirs Strategy | Always use their version | git merge -X theirs |
| rerere | Repeated similar conflicts | git config rerere.enabled true |
💡 Use the JSON Formatter tool to tidy up package.json after conflict resolution.
Cherry-Pick and Its Pitfalls
Cherry-pick lets you "pick" a specific commit onto the current branch without merging the entire branch.
Basic Usage
# Pick a single commit
git cherry-pick abc1234
# Pick multiple commits
git cherry-pick abc1234 def5678
# Pick a range (excludes start, includes end)
git cherry-pick start..end
# Pick a range (includes both start and end)
git cherry-pick start^..end
Common Pitfalls
Pitfall 1: Duplicate Commits
# Commit abc1234 on feature was already merged to main
# Later cherry-pick the same commit
git cherry-pick abc1234
# → Creates a new commit (different SHA) with same content
# → Git sees two different commits, future merge may produce empty merge or conflict
Pitfall 2: Missing Dependencies
# Commit B depends on Commit A's changes
# Only cherry-pick B without picking A
git cherry-pick B
# → May fail to compile or introduce bugs
Pitfall 3: Conflict Handling
# cherry-pick encounters conflict
git cherry-pick abc1234
# CONFLICT!
# Resolve conflict and continue
git add .
git cherry-pick --continue
# Or abort this cherry-pick
git cherry-pick --abort
Safe Cherry-Pick Principles
- Only cherry-pick to branches you don't plan to merge (e.g., hotfix to release)
- Ensure picked commits are self-contained (don't depend on other unpicked commits)
- Record cherry-picked commits to avoid duplication
- Prefer merge or rebase; cherry-pick is a last resort
Typical Scenario: Hotfix Sync
# Urgent fix on main
git checkout main
git cherry-pick hotfix-commit-sha
# Sync to develop
git checkout develop
git cherry-pick hotfix-commit-sha
# Sync to other release branches
git checkout release/v1.1
git cherry-pick hotfix-commit-sha
Bisect: Binary Search for Bugs
git bisect uses binary search to find the commit that introduced a bug, exponentially faster than linear checking.
Basic Flow
# 1. Start binary search
git bisect start
# 2. Mark current version as "bad"
git bisect bad
# 3. Mark a known good version
git bisect good v1.0.0
# Git auto-checkouts the middle commit
# Test this version...
# 4. Mark the middle commit
git bisect good # If this version is fine
git bisect bad # If this version has the bug
# 5. Repeat step 4 until Git finds the first bad commit
# → Git shows: abc1234 is the first bad commit
# 6. End binary search
git bisect reset
Automated Bisect
Use a script to automatically judge each commit:
# Use test script for automatic judgment
git bisect start HEAD v1.0.0 --
git bisect run npm test
# Use custom script
git bisect run ./scripts/bisect-test.sh
bisect-test.sh example:
#!/bin/bash
npm build || exit 125 # Skip commits that can't build
npm test
# exit 0 = good, exit 1 = bad, exit 125 = skip
Bisect Efficiency
For a range of 1000 commits, bisect needs at most 10 iterations (log₂(1000) ≈ 10) to locate the problematic commit, while linear search could take up to 1000.
Worktree: Parallel Work Without Branch Switching
git worktree lets you check out multiple branches into different directories in the same repo, without stash or clone.
Basic Usage
# Add a worktree
git worktree add ../feature-x feature/x
# → Checks out feature/x in ../feature-x directory
# Add a worktree with a new branch
git worktree add -b feature/y ../feature-y main
# → Creates feature/y branch and checks out in ../feature-y
# List all worktrees
git worktree list
# Remove a worktree
git worktree remove ../feature-x
# Force remove (when there are uncommitted changes)
git worktree remove --force ../feature-x
Typical Scenarios
# Scenario 1: Working on two features simultaneously
git worktree add ../feature-a feature/a
git worktree add ../feature-b feature/b
# → Two directories don't interfere, can open in different IDEs
# Scenario 2: Urgent fix without interrupting current work
git worktree add -b hotfix/urgent ../hotfix main
cd ../hotfix
# → Fix, commit, push
cd ../main-project
git worktree remove ../hotfix
# Scenario 3: Long-running tests
git worktree add ../test-branch test-env
# → Run tests in test-branch, continue dev in main directory
Worktree Notes
- The same branch cannot be checked out in two worktrees simultaneously
- Ensure changes are committed or saved before removing a worktree
- Worktrees share the same
.gitdirectory, saving disk space
Stash Advanced Usage
git stash temporarily saves uncommitted changes, the best way to "pause current work".
Basic Operations
# Save all changes (tracked file modifications and staging)
git stash
# Save with a description
git stash push -m "WIP: user auth refactor"
# View all stashes
git stash list
# Restore the latest stash
git stash pop
# Restore without deleting the stash
git stash apply
# Restore a specific stash
git stash apply stash@{2}
Advanced Techniques
# Stash only certain files
git stash push -m "partial" src/auth.ts src/auth.test.ts
# Stash untracked files (new files)
git stash -u
# Stash all files (including ignored files)
git stash -a
# Stash only staged content
git stash --staged
# View contents of a specific stash
git stash show -p stash@{0}
# Create a branch from a stash
git stash branch feature/from-stash stash@{0}
Managing Multiple Stashes
# Scenario: multiple stashes accumulated
git stash list
# stash@{0}: On feature/x: WIP: refactor
# stash@{1}: On feature/x: WIP: fix tests
# stash@{2}: On main: hotfix draft
# Delete a specific stash
git stash drop stash@{1}
# Clear all stashes
git stash clear
Stash and Conflicts
# When pop/apply encounters conflict
git stash pop
# CONFLICT!
# After resolving conflict, manually drop the stash
git stash drop
# Or abort the pop
git checkout -- .
git stash pop # retry
Git Hooks Automation
Git Hooks are scripts that execute automatically when specific Git events are triggered, a powerful tool for local automation.
Common Hooks Location
# Hooks are stored in .git/hooks/ directory
ls .git/hooks/
# applypatch-msg.sample
# pre-commit.sample
# commit-msg.sample
# ...
pre-commit: Pre-Commit Checks
# Create pre-commit hook
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# Check for console.log
if git diff --cached | grep -q "console.log"; then
echo "❌ Found console.log, please remove before committing"
exit 1
fi
# Run lint
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint check failed"
exit 1
fi
# Run type check
npm run typecheck
if [ $? -ne 0 ]; then
echo "❌ Type check failed"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/pre-commit
commit-msg: Enforce Commit Message Convention
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash
COMMIT_MSG=$(cat "$1")
# Validate Conventional Commits format
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,100}"
if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
echo "❌ Commit message doesn't follow Conventional Commits"
echo "Format: type(scope): description"
echo "Example: feat(auth): add login page"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/commit-msg
Recommended: Husky + lint-staged
Managing hooks manually isn't easy to share across teams. Use tools instead:
# Install Husky
npm install husky -D
npx husky init
# Add pre-commit hook
echo "npx lint-staged" > .husky/pre-commit
# Configure lint-staged (package.json)
# "lint-staged": {
# "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
# "*.{json,md}": ["prettier --write"]
# }
# Add commit-msg hook
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
Other Useful Hooks
| Hook | Trigger | Typical Use |
|---|---|---|
| pre-push | Before git push |
Run full test suite |
| post-merge | After git pull merge |
Auto npm install |
| post-checkout | After branch switch | Switch node_modules |
| prepare-commit-msg | Before editing commit message | Auto-add issue number |
Git LFS: Large File Storage
Git handles binary large files (images, videos, models) inefficiently. Git LFS solves this.
Installation & Initialization
# Install Git LFS
git lfs install
# Track large file types
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.model"
git lfs track "datasets/**"
# View tracking rules
git lfs track
# Commit .gitattributes (tracking rules must be versioned)
git add .gitattributes
git commit -m "chore: configure Git LFS"
Daily Usage
# Normal add/commit, LFS handles automatically
git add large-file.psd
git commit -m "feat: add design file"
# View LFS-stored files
git lfs ls-files
# View LFS storage usage
git lfs ls-files --size
# Pull LFS objects
git lfs pull
# Pull LFS objects for specific files only
git lfs fetch --include="*.psd"
Migrating Existing Files to LFS
# Migrate tracked .psd files to LFS
git lfs migrate import --include="*.psd"
# Migrate large files in all history (rewrites history!)
git lfs migrate import --include="*.psd" --everything
LFS Notes
- Requires server support (GitHub/GitLab both support it, with quota limits)
.gitattributesmust be committed to the repo- Clone doesn't download LFS objects by default (needs
git lfs pull) - LFS has storage and bandwidth quotas; watch costs
Monorepo Strategies
Monorepo places multiple projects in the same repository, making it easier to share code and manage uniformly.
Directory Structure
monorepo/
├── apps/
│ ├── web/ # Frontend app
│ ├── mobile/ # Mobile app
│ └── api/ # Backend service
├── packages/
│ ├── ui/ # Shared UI components
│ ├── utils/ # Shared utility functions
│ └── config/ # Shared configuration
├── package.json
├── turbo.json # Turborepo config
└── pnpm-workspace.yaml
Sparse Checkout
Only check out needed directories, speeding up clone:
# Enable sparse checkout
git sparse-checkout init --cone
# Only check out apps/web and packages/ui
git sparse-checkout set apps/web packages/ui
# Add more directories
git sparse-checkout add apps/api
# View currently checked-out directories
git sparse-checkout list
Shallow Clone
Only fetch recent commit history:
# Only fetch the latest 1 commit
git clone --depth=1 https://github.com/org/monorepo.git
# Fetch the latest 10 commits
git clone --depth=10 https://github.com/org/monorepo.git
# Fetch more history later
git fetch --unshallow
Monorepo Tool Choices
| Tool | Language | Core Feature |
|---|---|---|
| Turborepo | JS/TS | Incremental builds, remote caching, Pipeline |
| Nx | JS/TS | Dependency graph analysis, affected project detection |
| Lerna | JS/TS | Version management, publish workflow |
| Bazel | Multi-language | Google-grade incremental builds |
| PNPM Workspace | JS/TS | Native monorepo support |
Common Errors & Rescue
Detached HEAD
# Accidentally entered detached HEAD state
git checkout abc1234
# → HEAD detached at abc1234
# Check current state
git status
# → HEAD detached at abc1234
# Rescue option 1: Create new branch to preserve
git checkout -b feature/from-detached
# Rescue option 2: If you have uncommitted changes
git stash
git checkout main
git stash pop
Force Push Recovery
# Someone force-pushed and overwrote the remote branch
# 1. Use reflog to find the overwritten commit
git reflog
# abc1234 HEAD@{0}: checkout: moving from main to feature/x
# def5678 HEAD@{1}: commit: feat: important feature
# 2. Restore to the specific commit
git checkout def5678
git checkout -b feature/x-recovered
git push -f origin feature/x-recovered:feature/x
Reflog: The Ultimate Rescue Tool
Reflog records every movement of HEAD. Even "deleted" commits can be recovered:
# View full reflog
git reflog
# View reflog for a specific branch
git reflog show feature/x
# View the last 10 entries
git reflog -10
# Restore to a reflog entry
git reset --hard HEAD@{5}
# Recover commits lost by reset
git reflog
# Find the commit SHA before the reset
git cherry-pick <lost-commit-sha>
Reflog retention time:
[gc]
reflogExpire = 90.days
reflogExpireUnreachable = 30.days
Accidentally Committed Large File
# 1. Completely remove large file from history
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch path/to/large-file.mp4' \
--prune-empty -- --all
# 2. Or use the faster git-filter-repo
pip install git-filter-repo
git filter-repo --path path/to/large-file.mp4 --invert-paths
# 3. Force push to update remote
git push --force --all
# 4. Clean up locally
git reflog expire --expire=now --all
git gc --prune=now --aggressive
.gitignore Best Practices
Layered Strategy
# Global ignore (~/.gitignore_global)
# OS files
.DS_Store
Thumbs.db
Desktop.ini
# IDE
.idea/
.vscode/
*.swp
# Environment variables
.env
.env.local
Project-Level .gitignore
# Dependencies
node_modules/
vendor/
.venv/
# Build output
dist/
build/
*.egg-info/
# Logs
*.log
logs/
# Test coverage
coverage/
.nyc_output/
# Temporary files
*.tmp
*.temp
.cache/
# Large files (use LFS instead of ignoring)
# *.psd → use LFS tracking, not ignore
Ignore Rule Syntax
# Ignore all .log files
*.log
# But keep important.log
!important.log
# Ignore all contents under build directory
build/**
# Ignore TODO in root only, not in subdirectories
/TODO
# Ignore all .pdf under doc directory
doc/**/*.pdf
# Ignore __pycache__ in all directories
__pycache__/
Common Mistakes
# ❌ Wrong: Adding already-tracked files to .gitignore has no effect
# ✅ Correct: Untrack first, then ignore
git rm --cached debug.log
# Then add to .gitignore
echo "debug.log" >> .gitignore
git add .gitignore
git commit -m "chore: ignore debug.log"
Recommended Templates
Use gitignore.io to generate project templates:
# Generate ignore rules for Node + VSCode + macOS
curl -sL https://www.gitignore.io/api/node,visualstudiocode,macos > .gitignore
💡 Use the Base64 Encode tool to encode sensitive information in .env files for transmission.
FAQ
Q1: Too many conflicts during rebase, what to do?
Options:
git rebase --abortand usegit mergeinstead- Rebase from upstream frequently to reduce accumulated differences
- Split large features into smaller ones to reduce rebase scope
Q2: How to undo a pushed commit?
# Option 1: revert (safe, creates new commit)
git revert abc1234
git push
# Option 2: reset + force push (dangerous, rewrites history)
git reset --hard abc1234^
git push --force
# ⚠️ Only use when sure no one else is based on this commit
Q3: How to view modification history of a specific file?
# View file modification history
git log --follow -p src/auth/login.ts
# See who modified each line
git blame src/auth/login.ts
# View file content at a specific commit
git show abc1234:src/auth/login.ts
Q4: How to compare differences between two branches?
# View file differences between branches
git diff main..feature/x
# View commit differences between branches
git log main..feature/x --oneline
# View statistics between branches
git diff main..feature/x --stat
Q5: How to clean up local references to deleted remote branches?
# Prune remote branch references that no longer exist
git remote prune origin
# Or auto-prune during fetch
git fetch -p
# Or configure auto-pruning
git config --global fetch.prune true
Q6: How to revert a merge commit?
# Reverting a merge commit requires specifying which parent to keep
# -m 1: keep first parent (usually main)
git revert -m 1 <merge-commit-sha>
Q7: How to make Git ignore file permission changes?
git config core.fileMode false
Q8: How to speed up cloning of large repositories?
# Combined strategy: shallow clone + sparse checkout + single branch
git clone --depth=1 --single-branch --filter=blob:none \
https://github.com/org/large-repo.git
Try these browser-local tools — no sign-up required →