Understanding git diff in Daily Workflows
When you're working on a feature that touches multiple files across your codebase, it's easy to lose track of what you've actually changed. The ability to see exactly what changed—line by line, file by file, or even word by word—is what separates a confident developer from one who commits nervously and hopes the code review goes smoothly. This guide explores git diff tips in Git & GitHub for Professional Developers, focusing on the practical scenarios you'll encounter when managing changes across staging, commits, and branches.
git diff for Unstaged Changes
The most common use case is checking what you've modified but haven't yet staged. When you run git diff without arguments, Git shows you all changes in your working directory that haven't been added to the staging area.
git diffThis command displays a unified diff format showing removed lines (prefixed with -) and added lines (prefixed with +). In a real-world scenario, imagine you're refactoring a payment service. You've been editing three files: PaymentProcessor.cs, TransactionLogger.cs, and RefundHandler.cs. Before staging anything, running git diff lets you verify each change makes sense in isolation.
diff --git a/PaymentProcessor.cs b/PaymentProcessor.cs
index abc1234..def5678 100644
--- a/PaymentProcessor.cs
+++ b/PaymentProcessor.cs
@@ -45,7 +45,7 @@ public class PaymentProcessor
{
public async Task<Result> ProcessPayment(Payment payment)
{
- var fee = payment.Amount * 0.029m;
+ var fee = CalculateFee(payment.Amount);
return await _gateway.Charge(payment, fee);
}
}You can also view changes for a specific file to narrow your focus:
git diff PaymentProcessor.csThis is particularly useful when you've modified many files and want to review one at a time before staging. In most professional teams, this is your first checkpoint before committing.
git diff --staged for Staged Changes
Once you've staged changes with git add, they move into the staging area. To review what's actually going to be committed, use git diff --staged (or the older alias git diff --cached).
git diff --stagedThis is your second checkpoint and arguably more critical. You're now looking at exactly what will be included in your next commit. In a pull request scenario, this is what reviewers will see. Let's say you've staged changes to implement a retry mechanism in your transaction handler:
git add TransactionHandler.cs
git diff --staged TransactionHandler.csThe output might show:
diff --git a/TransactionHandler.cs b/TransactionHandler.cs
index 1a2b3c4..5d6e7f8 100644
--- a/TransactionHandler.cs
+++ b/TransactionHandler.cs
@@ -10,6 +10,15 @@ public class TransactionHandler
private const int MaxRetries = 3;
private const int RetryDelayMs = 1000;
+ public async Task<bool> ExecuteWithRetry(Func<Task> operation)
+ {
+ for (int attempt = 0; attempt < MaxRetries; attempt++)
+ {
+ try
+ {
+ await operation();
+ return true;
+ }
+ catch (TransientException ex)A common pattern in our team is running git diff --staged before every commit, even if you think you know what you staged. It catches accidental inclusions, debug code, or files you meant to exclude.
git diff main...feature for Branch Changes
When you're working on a feature branch, understanding the accumulated changes from your branch point is essential. Use the three-dot syntax to compare your feature branch against the main branch:
git diff main...feature-retry-logicThis shows all changes introduced on your feature branch since it diverged from main. Note the three dots (...): this is different from two dots (..), which would show changes on main that are not on your feature branch.
Here's a practical scenario: you've been working on a feature branch for three days and want to see the big picture before opening a pull request. Running this command gives you the complete diff of your work. If you've made 15 commits with intermediate fixes, this single command shows the net result rather than forcing you through every commit individually.
git diff main...feature-retry-logic --statAdding --stat shows a summary: which files changed and how many lines were added or removed. This is excellent for communicating scope in pull request descriptions or during team standups.
You can also compare against a specific commit or tag:
git diff v1.2.0...feature-new-endpointThis helps when you need to understand what changed relative to a release version rather than a branch.
--word-diff for Prose and Configuration
The default line-based diff works well for code, but when you're modifying configuration files, documentation, or any prose-heavy content, line-based diffs can be hard to parse. Use --word-diff to highlight changes at the word level instead:
git diff --word-diffConsider a README update where you're revising deployment instructions. A line-based diff might show:
-Deploy to production using the legacy manual process with SSH keys stored in the vault.
+Deploy to production using the automated CI/CD pipeline with credentials managed by AWS Secrets Manager.With --word-diff, you see:
Deploy to production using the [-legacy manual process-] {+automated CI/CD pipeline+} with {+credentials managed by AWS Secrets Manager+}.The change is immediately clear without having to parse removed and added lines separately. For YAML or JSON configuration changes, this can be the difference between quickly verifying a change and spending minutes cross-referencing diffs.
You can also use color-words mode for even cleaner output:
git diff --color-wordsThis highlights only the changed words inline, making it ideal for reviewing parameter changes, endpoint modifications, or documentation corrections.
Practical Combinations and Flags
In real workflows, you'll often combine these commands with additional flags. Here are patterns we use regularly:
git diff -U5shows 5 lines of context around each change instead of the default 3, helpful when changes are clustered.git diff --ignore-space-changeignores whitespace differences, useful when reviewing after auto-formatting.git diff main feature -- src/limits the diff to a specific directory.git diff --name-only main...featurelists only filenames that changed, not the actual diffs.git diff --name-status main...featureadds modification status (A for added, M for modified, D for deleted).
For very large changes, pipe the output to less:
git diff main...feature | lessOr save to a file for offline review or sharing:
git diff main...feature > feature.patchCommon Mistakes
Confusing two dots and three dots: Two dots (git diff main..feature) shows changes unique to feature; three dots shows changes on feature since it diverged from main. Use three dots for PR reviews.
Forgetting to check staged changes before committing: Running git diff (unstaged) after staging everything won't show you what's being committed. Always use git diff --staged before the final commit.
Not using --stat for high-level overview: When reviewing large branches, jump straight to git diff --stat to understand scope before diving into line-by-line diffs.
Ignoring whitespace and formatting changes: If your editor auto-formats files, use --ignore-space-change or --ignore-all-space to focus on actual logic changes, not formatting.
Reviewing diffs on GitHub instead of locally: GitHub's diff viewer is good, but it can be slow for large PRs. Use local git diff commands for faster review, especially when you need to search or jump around.
Key Takeaways
- Use
git diffto review unstaged changes before staging, andgit diff --stagedbefore committing—these are your checkpoints against mistakes. - Use
git diff main...featureto see all changes on a feature branch since branching, essential for PR prep. - Use
--word-diffor--color-wordsfor prose, configuration, and documentation changes where line-based diffs are hard to parse. - Combine with
--stat,--name-only, or directory filters to quickly understand scope before diving into details. - Review diffs locally using Git commands for speed and power; GitHub diffs are for collaboration, not your primary review tool.






Comments
Loading comments…