ls-tree Git Command Guide
The git ls-tree command lists the contents of a given tree object, similar to /bin/ls -a but for Git tree objects. It shows file modes, types, object hashes, and filenames, enabling detailed examination of repository structure at any commit.
git ls-tree Syntax:
Section titled “git ls-tree Syntax:”git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--object-only] [--full-name] [--full-tree] [--abbrev[=<n>]] [--format=<format>] <tree-ish> [<path>...]Display Options:
Section titled “Display Options:”| Option | Description |
|---|---|
-d | Show only directories |
-r | Recurse into subdirectories |
-t | Sort by tree/file type |
-l | Show file size |
-z | Use NUL line termination |
--name-only | Show only filenames |
--name-status | Show filename and status |
--object-only | Show only object hashes |
--full-name | Show full path from repository root |
--full-tree | Ignore current working directory |
--abbrev[=<n>] | Abbreviate object hashes |
--format=<format> | Custom output format |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<tree-ish> | Tree object, commit, or branch to examine |
<path>... | Specific paths to show (relative to tree-ish) |
Basic Usage Examples:
Section titled “Basic Usage Examples:”View Tree Contents:
Section titled “View Tree Contents:”# Show root tree contentsgit ls-tree HEAD
# Show specific commit treegit ls-tree v1.0.0
# Show current index treegit ls-tree --name-only HEADDirectory and File Analysis:
Section titled “Directory and File Analysis:”# Show only directoriesgit ls-tree -d HEAD
# Show only files (not directories)git ls-tree HEAD | grep -v "^040000"
# Show file sizesgit ls-tree -l HEADRecursive Tree Exploration:
Section titled “Recursive Tree Exploration:”# Recurse into all subdirectoriesgit ls-tree -r HEAD
# Show specific subdirectorygit ls-tree HEAD src/
# Show multiple pathsgit ls-tree HEAD src/ tests/ docs/Object Information:
Section titled “Object Information:”# Show object hashes onlygit ls-tree --object-only HEAD
# Show abbreviated hashesgit ls-tree --abbrev=8 HEAD
# Show full pathsgit ls-tree --full-name HEADAdvanced Tree Operations:
Section titled “Advanced Tree Operations:”Tree Comparison:
Section titled “Tree Comparison:”# Compare trees between commitsgit ls-tree HEAD src/ > current-tree.txtgit ls-tree HEAD~1 src/ > previous-tree.txtdiff current-tree.txt previous-tree.txt
# Find new files in current commitcomm -23 <(git ls-tree HEAD~1 --name-only) <(git ls-tree HEAD --name-only)File Type Analysis:
Section titled “File Type Analysis:”# Count files by typegit ls-tree -r HEAD | awk '{print $2}' | sort | uniq -c | sort -rn
# Find all executable filesgit ls-tree -r HEAD | awk '$1 ~ /100755/ {print $4}'
# Find all symlinksgit ls-tree -r HEAD | awk '$2 == "commit" {print $4}'Repository Structure Analysis:
Section titled “Repository Structure Analysis:”# Directory structure overviewgit ls-tree --name-only HEAD | xargs -I {} dirname {} | sort | uniq -c | sort -rn
# Deepest directory pathsgit ls-tree -r --name-only HEAD | awk -F/ '{print NF-1 ": " $0}' | sort -rn | head -10
# File extension distributiongit ls-tree -r --name-only HEAD | grep -E "\.[a-zA-Z0-9]+$" | sed 's/.*\.//' | sort | uniq -c | sort -rnIntegration with Other Commands:
Section titled “Integration with Other Commands:”Complete Repository Inspection:
Section titled “Complete Repository Inspection:”#!/bin/bash# Comprehensive repository analysisecho "=== REPOSITORY STRUCTURE ==="git ls-tree -r --name-only HEAD | wc -l && echo "total files"
echo "=== FILE TYPES ==="git ls-tree -r HEAD | awk '{print $2}' | sort | uniq -c | sort -rn
echo "=== LARGEST FILES ==="git ls-tree -r -l HEAD | awk '$5 > 1000000 {print $5 ": " $6}' | sort -rn | head -5
echo "=== RECENTLY MODIFIED ==="git ls-tree -r HEAD | while read mode type hash size path; do echo "$(git log -1 --format=%ci "$hash" 2>/dev/null || echo "unknown") $path"done | sort -r | head -10Tree Object Validation:
Section titled “Tree Object Validation:”# Verify tree object integritytree_hash=$(git rev-parse HEAD^{tree})echo "Tree hash: $tree_hash"
# List tree contentsgit ls-tree "$tree_hash" | wc -l && echo "entries"
# Verify all objects existgit ls-tree -r "$tree_hash" | while read mode type hash path; do if ! git cat-file -e "$hash" 2>/dev/null; then echo "Missing object: $hash ($path)" fidoneHistorical Tree Comparison:
Section titled “Historical Tree Comparison:”# Compare directory contents between commitscompare_trees() { local commit1="$1" local commit2="$2" local path="$3"
echo "=== Changes in $path between $commit1 and $commit2 ===" comm -23 \ <(git ls-tree "$commit1" "$path" | awk '{print $4}' | sort) \ <(git ls-tree "$commit2" "$path" | awk '{print $4}' | sort)}
# Usagecompare_trees HEAD~1 HEAD src/Performance and Optimization:
Section titled “Performance and Optimization:”Large Repository Handling:
Section titled “Large Repository Handling:”# Limit depth for large reposgit ls-tree HEAD | head -50
# Process specific subdirectoriesgit ls-tree HEAD src/ | wc -l
# Use name-only for faster processinggit ls-tree --name-only HEAD | grep "\.js$" | wc -lBatch Processing:
Section titled “Batch Processing:”# Process files in batchesgit ls-tree -r --name-only HEAD | split -l 1000 - file-batch-
# Process each batchfor batch in file-batch-*; do echo "Processing batch: $batch" cat "$batch" | xargs process-filesdoneTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Tree Object Not Found:
Section titled “Tree Object Not Found:”# Check if commit existsgit cat-file -t HEAD
# Verify tree hashgit rev-parse HEAD^{tree}
# Check repository integritygit fsck --unreachable | head -10Permission Issues:
Section titled “Permission Issues:”# Check object accessibilitygit cat-file -t $(git ls-tree HEAD | head -1 | awk '{print $3}')
# Verify repository permissionsls -la .git/objects/Encoding Problems:
Section titled “Encoding Problems:”# Handle filename encodinggit ls-tree HEAD | iconv -f utf-8 -t utf-8
# Check for problematic filenamesgit ls-tree -z HEAD | xargs -0 -I {} echo "'{}'"Performance Issues:
Section titled “Performance Issues:”# Time tree operationstime git ls-tree -r HEAD > /dev/null
# Use specific paths for speedgit ls-tree HEAD src/ | wc -l
# Cache results for repeated queriesgit ls-tree --name-only HEAD > /tmp/tree-cache.txtReal-World Usage Examples:
Section titled “Real-World Usage Examples:”Codebase Analysis:
Section titled “Codebase Analysis:”#!/bin/bash# Analyze project structureecho "=== PROJECT STATISTICS ==="
# Total files by typeecho "Files by type:"git ls-tree -r HEAD | awk '{print $2}' | sort | uniq -c | sort -rn
# Source code filessrc_files=$(git ls-tree -r --name-only HEAD | grep -E "\.(c|cpp|java|py|js|ts|go|rs)$" | wc -l)echo "Source files: $src_files"
# Documentation filesdocs=$(git ls-tree -r --name-only HEAD | grep -E "\.(md|txt|rst|doc)$" | wc -l)echo "Documentation files: $docs"
# Configuration filesconfig=$(git ls-tree -r --name-only HEAD | grep -E "(config|conf|ini|yaml|yml|json|toml)$" | wc -l)echo "Configuration files: $config"Dependency Analysis:
Section titled “Dependency Analysis:”# Find dependency filesdeps=$(git ls-tree -r --name-only HEAD | grep -E "(package\.json|requirements\.txt|Gemfile|Cargo\.toml|go\.mod)$")echo "Dependency files found:"echo "$deps"
# Check for lock fileslocks=$(git ls-tree -r --name-only HEAD | grep -E "(package-lock\.json|yarn\.lock|Pipfile\.lock|Gemfile\.lock|Cargo\.lock)")if [ -n "$locks" ]; then echo "Lock files present (good for reproducible builds):" echo "$locks"else echo "No lock files found - consider adding for reproducible builds"fiSecurity Scanning:
Section titled “Security Scanning:”#!/bin/bash# Security-focused repository analysis
echo "=== SECURITY SCAN ==="
# Check for sensitive files that shouldn't be trackedsensitive_patterns=( "\.env" "\.key" "\.pem" "password" "secret" "credential")
for pattern in "${sensitive_patterns[@]}"; do found=$(git ls-tree -r --name-only HEAD | grep -i "$pattern" | wc -l) if [ "$found" -gt 0 ]; then echo "WARNING: Found $found files matching '$pattern'" git ls-tree -r --name-only HEAD | grep -i "$pattern" fidone
# Check file permissionsecho "=== FILE PERMISSIONS ==="git ls-tree -r HEAD | awk '$1 !~ /^(100644|100755|120000|160000)/ {print "Unusual permissions: " $1 " " $4}'How does ls-tree differ from git ls-files?
Section titled “How does ls-tree differ from git ls-files?”git ls-files shows index contents; git ls-tree shows tree object contents. ls-tree examines historical or specific commit trees, ls-files shows current index state.
Can ls-tree show file contents?
Section titled “Can ls-tree show file contents?”No, shows tree entries (metadata). Use git show
What’s the relationship between tree objects and commits?
Section titled “What’s the relationship between tree objects and commits?”Each commit points to a tree object representing repository state. Tree objects contain file/blob references and subdirectories.
How do I examine a specific file in historical commit?
Section titled “How do I examine a specific file in historical commit?”Use git ls-tree
What’s the performance impact of -r (recursive) option?
Section titled “What’s the performance impact of -r (recursive) option?”Recursive traversal examines entire repository tree - expensive for large repositories. Use specific paths when possible for better performance.
Can ls-tree work with remote repositories?
Section titled “Can ls-tree work with remote repositories?”No, operates on local tree objects. Use git fetch to get remote trees, then examine with ls-tree, or use git ls-remote for remote reference inspection.
How do I interpret the mode field in ls-tree output?
Section titled “How do I interpret the mode field in ls-tree output?”Mode shows file type and permissions: 100644 (regular file), 100755 (executable), 120000 (symlink), 160000 (submodule), 040000 (directory).
What’s the difference between —name-only and —object-only?
Section titled “What’s the difference between —name-only and —object-only?”—name-only shows filenames only; —object-only shows object hashes only. Both suppress other metadata for focused output.
Can ls-tree detect file renames or moves?
Section titled “Can ls-tree detect file renames or moves?”No, shows current tree structure. Use git log —follow —name-status to detect renames across commits, or git diff for recent changes.
How do I use ls-tree in scripts?
Section titled “How do I use ls-tree in scripts?”Use -z for NUL termination with filenames containing spaces. Parse output carefully - format may change between Git versions.
What’s the —full-tree option for?
Section titled “What’s the —full-tree option for?”Ignores current working directory context, treating paths as relative to tree root. Useful when tree-ish doesn’t represent current working directory state.
Can ls-tree show information about submodules?
Section titled “Can ls-tree show information about submodules?”Yes, shows submodule entries with mode 160000 and commit hash. Use git submodule status for detailed submodule information.
How do I compare tree contents between commits?
Section titled “How do I compare tree contents between commits?”Use comm or diff with git ls-tree output: comm -23 <(git ls-tree HEAD —name-only) <(git ls-tree HEAD~1 —name-only) shows new files.
What’s the relationship between ls-tree and git read-tree?
Section titled “What’s the relationship between ls-tree and git read-tree?”ls-tree examines tree contents; read-tree updates index with tree contents. ls-tree is read-only, read-tree modifies repository state.
Can ls-tree work with tag objects?
Section titled “Can ls-tree work with tag objects?”Yes, tags point to commits which point to trees. Use git ls-tree
How do I handle large tree output?
Section titled “How do I handle large tree output?”Use head/tail for limiting: git ls-tree -r HEAD | head -100. Use specific paths: git ls-tree HEAD src/ instead of entire repository.
What’s the —abbrev option for?
Section titled “What’s the —abbrev option for?”Controls hash abbreviation length. Default shows full 40-character SHA-1. Use —abbrev=8 for shorter, more readable output.
Can ls-tree show line ending information?
Section titled “Can ls-tree show line ending information?”No, that’s git ls-files —eol functionality. ls-tree shows tree object metadata, not working directory file properties.
How do I use ls-tree for repository archaeology?
Section titled “How do I use ls-tree for repository archaeology?”Examine historical trees: git ls-tree
What’s the difference between tree-ish and commit-ish?
Section titled “What’s the difference between tree-ish and commit-ish?”Both work with ls-tree, but tree-ish refers specifically to tree objects while commit-ish refers to any object resolving to commit (which has tree).
Applications of the git ls-tree command
Section titled “Applications of the git ls-tree command”- Repository Structure Analysis: Examine directory and file organization at any commit
- Historical Investigation: Understand repository state and file locations at specific points in time
- Content Validation: Verify file existence and metadata in tree objects
- Build System Integration: Generate file lists for compilation or packaging processes
- Security Auditing: Identify file types and locations for security scanning
- Migration Planning: Analyze repository structure for refactoring or reorganization projects