Comprehensive Git Diff Analysis: A Developer’s Guide
Analyzing changes between Git branches can be cumbersome without the right tools. This guide presents two robust solutions:
- A one-liner function for quick terminal use.
- A reusable shell script for automation.
Both solutions provide detailed insights into branch differences, including new, modified, deleted, and renamed files, with features like sorting and conflict detection.
Table of Contents
- Introduction
- Problem Statement
- Features
- One-Liner Function
- Shell Script
- Use Cases
- Error Handling
- Conclusion
Introduction
Tracking changes between Git branches is critical during code reviews, debugging, or merging processes. This guide simplifies Git diff analysis using a one-liner or shell script, empowering developers to efficiently inspect file changes and conflicts.
Problem Statement
Without proper tools, Git branch comparisons can be:
- Time-consuming.
- Difficult to categorize into New, Modified, Deleted, and Renamed files.
- Lacking clarity with merge conflict detection.
Features
- Categorized Output: Changes are grouped into New, Modified, Deleted, and Renamed files.
- Merge Conflict Detection: Identify files causing conflicts during merges.
- Sorting: Files can be listed in ascending or descending alphabetical order.
- Serial Numbering: Each file is numbered for easy reference.
- Error Handling: The solution ensures proper validation of input parameters and environment setup.
One-Liner Function
Code
git_compare() {
d=${1:-$PWD}; s=${2:-master}; t=${3:-$(git branch --show-current)}; sort=${4:-asc}; f=${5:-". "}; conf=${6:-false}; total=0;
cd "$d" 2>/dev/null || { echo "Error: Invalid directory"; return 1; };
git rev-parse --git-dir >/dev/null 2>&1 || { echo "Error: Not a git repo"; return 1; };
git rev-parse --verify "$s" >/dev/null 2>&1 || { echo "Error: Branch '$s' not found"; return 1; };
git rev-parse --verify "$t" >/dev/null 2>&1 || { echo "Error: Branch '$t' not found"; return 1; };
echo "=== Git Diff Analysis ($(git --version)) ==="; echo "Source → Target: $s → $t"; echo "Directory: $d"; echo "Sort: $sort | Conflicts: $conf";
for c in "A:New" "M:Modified" "D:Deleted" "R:Renamed"; do
echo -e "\n>> ${c#*:} files:";
if [[ "${c%%:*}" == "R" ]]; then
git diff --name-status --diff-filter=R "$s..$t" | sort $([[ "$sort" == "desc" ]] && echo "-r") | awk -v fmt="$f" '{printf "%d%s%s → %s\n", NR, fmt, $2, $3}'
else
git diff --name-status --diff-filter=${c%%:*} "$s..$t" | sort $([[ "$sort" == "desc" ]] && echo "-r") | awk -v fmt="$f" '{printf "%d%s%s\n", NR, fmt, $2}'
fi
count=$(git diff --name-status --diff-filter=${c%%:*} "$s..$t" | wc -l);
total=$((total + count)); echo "Total: $count";
done
if [[ "$conf" == "true" ]]; then
echo -e "\n>> Conflict files:";
conflicts=$(git diff --name-only --diff-filter=U "$s..$t" | sort $([[ "$sort" == "desc" ]] && echo "-r"));
if [[ -z "$conflicts" ]]; then echo "None"; else
echo "$conflicts" | awk -v fmt="$f" '{printf "%d%s%s\n", NR, fmt, $0}';
total=$((total + $(echo "$conflicts" | wc -l))); fi;
fi
echo -e "\n=== Summary ==="; echo "Total files affected: $total";
}
Usage
- Paste the function into your terminal.
- Call it with parameters:
git_compare [directory] [source_branch] [target_branch] [sort_order] [format] [show_conflicts]
Example Usage
- Basic comparison:
git_compare
Compares the current branch with master
in the current directory.
- Specific directory and branches:
git_compare /path/to/repo develop feature
- Descending order with conflict detection:
git_compare /repos/main main feature desc ": " true
Example Output
=== Git Diff Analysis (git version 2.43.0) ===
Source → Target: master → feature/awesome-update
Directory: .
Sort: asc | Conflicts: false
>> New files:
1. src/new_file1.js
2. src/new_file2.php
Total: 2
>> Modified files:
1. src/modified_file.php
2. src/utils/helper.js
Total: 2
>> Deleted files:
N/A
Total: 0
>> Renamed files:
1. src/old_name.php → src/new_name.php
Total: 1
=== Summary ===
Total files affected: 5
Shell Script
Code
#!/bin/bash
set -e
dir=${1:-$(pwd)}
src=${2:-master}
tgt=${3:-$(git branch --show-current)}
sort=${4:-asc}
fmt=${5:-". "}
conf=${6:-false}
total=0
cd "$dir" || { echo "Error: Invalid directory"; exit 1; }
git rev-parse --git-dir >/dev/null || { echo "Error: Not a git repo"; exit 1; }
git rev-parse --verify "$src" >/dev/null || { echo "Error: Branch '$src' not found"; exit 1; }
git rev-parse --verify "$tgt" >/dev/null || { echo "Error: Branch '$tgt' not found"; exit 1; }
process() {
local filter=$1 label=$2 sflag=$([[ "$sort" == "desc" ]] && echo "-r" || echo "")
echo ">> $label Files:"
if [[ $filter == "R" ]]; then
git diff --name-status --diff-filter=R "$src..$tgt" | sort $sflag | awk -v fmt="$fmt" 'NF{printf "%d%s%s → %s\n", NR, fmt, $2, $3; c++}END{print "Total:",c+0}'
else
git diff --name-status --diff-filter="$filter" "$src..$tgt" | sort $sflag | awk -v fmt="$fmt" 'NF{printf "%d%s%s\n", NR, fmt, $2; c++}END{print "Total:",c+0}'
fi
}
for c in "A:New" "M:Modified" "D:Deleted" "R:Renamed"; do
process "${c%%:*}" "${c#*:}"
done
if [[ "$conf" == "true" ]]; then
echo ">> Conflict Files:"
git diff --name-only --diff-filter=U "$src..$tgt" | sort $([[ "$sort" == "desc" ]] && echo "-r") | awk -v fmt="$fmt" 'NF{printf "%d%s%s\n", NR, fmt, $0; c++}END{print "Total:",c+0}'
fi
echo "Total Files: $total"
Example Usage
- Save as
git_compare.sh
. - Run:
bash git_compare.sh [directory] [source_branch] [target_branch] [sort_order] [format] [show_conflicts]
Use Cases
- Code Reviews: Analyze changes in pull requests.
- Merge Prep: Detect and resolve conflicts before merging.
- Audit: Track file modifications for debugging or compliance.
Error Handling
- Invalid Directory: Displays "Error: Invalid directory".
- Non-Git Repository: Displays "Error: Not a git repository".
- Branch Not Found: Displays "Error: Branch '' not found".
Conclusion
The provided one-liner function and shell script simplify Git diff analysis with a feature-rich and customizeable approach. Tailor the tools to suit your workflow and boost
productivity.
Top comments (0)