How to Get a List of New, Modified, or Deleted Files/Directories in Git: Comparing Local and Remote Repositories
Git is the cornerstone of modern version control, enabling collaboration and tracking changes across distributed teams. A common challenge developers face is understanding how their local repository differs from the remote (e.g., GitHub, GitLab, or Bitbucket). Whether you’re preparing to push changes, reviewing updates from teammates, or troubleshooting discrepancies, knowing how to identify new, modified, or deleted files/directories between local and remote repositories is critical.
This guide will walk you through step-by-step methods to compare your local repository with the remote, using Git commands to list changes clearly. We’ll cover basic comparisons, interpreting status codes, advanced filtering, and troubleshooting common issues. By the end, you’ll confidently identify file-level differences and streamline your workflow.
Table of Contents#
- Prerequisites
- Understanding Local vs. Remote Repositories
- Step 1: Fetch the Latest Remote Changes
- Step 2: Compare Local and Remote Branches
- Step 3: Interpreting Git Status Codes
- Step 4: Advanced Comparisons (Specific Files, Commit Ranges)
- Step 5: Handling Detached HEAD or Stashed Changes
- Troubleshooting Common Issues
- Conclusion
- References
Prerequisites#
Before proceeding, ensure you have:
- Git installed: Verify with
git --version(install from git-scm.com if missing). - A local Git repository: Clone an existing repo with
git clone <remote-url>or initialize one withgit init. - Access to the remote repository: You must have network access to fetch/push (e.g., GitHub, GitLab credentials).
- Basic Git knowledge: Familiarity with
git add,git commit,git branch, andgit remotecommands.
Understanding Local vs. Remote Repositories#
- Local Repository: Resides on your machine, containing your working directory (files you edit), staging area (files marked for commit), and local branches (committed history).
- Remote Repository: A centralized repo hosted elsewhere (e.g., GitHub). It acts as a shared hub for team collaboration.
- Remote-Tracking Branches: Local references (e.g.,
origin/main) that mirror the state of remote branches. These are updated when you rungit fetchorgit pull.
To compare local and remote, you first need to update your remote-tracking branches (via git fetch) to reflect the latest changes on the remote.
Step 1: Fetch the Latest Remote Changes#
Before comparing, always fetch remote updates to ensure your local remote-tracking branches (e.g., origin/main) are up-to-date. This avoids comparing against stale data.
Commands:#
-
Check your remotes: Confirm the remote name (usually
originby default):git remote -vOutput example:
origin https://github.com/your-username/your-repo.git (fetch) origin https://github.com/your-username/your-repo.git (push) -
Fetch remote changes: Update remote-tracking branches without merging them into your local branch:
git fetch originorigin: The name of your remote (replace with your remote name if different).- This command downloads new commits, branches, or tags from the remote but leaves your local working directory unchanged.
Step 2: Compare Local and Remote Branches#
Once you’ve fetched remote changes, use git diff to compare your local branch with its remote counterpart. The goal is to list files/directories that differ, not just view content changes.
Key Command: git diff --name-status <local-branch> <remote-branch>#
--name-status: Shows filenames and their status (added, modified, deleted) instead of full content diffs.<local-branch>: Your local branch (e.g.,main,feature/login).<remote-branch>: The remote-tracking branch (e.g.,origin/main).
Example Workflow:#
Suppose you’re on the main branch and want to compare it with origin/main (the remote main branch):
-
Ensure you’re on the local branch:
git checkout main # Switch to main if not already on it -
Compare with the remote branch:
git diff --name-status main origin/main
Sample Output:#
A src/new-file.txt
M docs/user-guide.md
D tests/old-test.js
This output lists:
A:src/new-file.txtwas added locally but not on the remote.M:docs/user-guide.mdwas modified locally.D:tests/old-test.jswas deleted locally.
Alternative: Compare Current Branch Automatically#
If your local branch is tracking a remote branch (the default for cloned repos), simplify the command to:
git diff --name-status @{u} @{u}(short for@{upstream}) refers to the remote branch your local branch is tracking (e.g.,origin/mainformain).
Step 3: Interpreting Git Status Codes#
The --name-status flag uses single-letter codes to describe file changes. Here’s what each code means:
| Code | Description |
|---|---|
A | Added: File exists in local but not in remote (new file). |
C | Copied: File was copied from another file (requires --find-copies-harder). |
D | Deleted: File exists in remote but not in local (deleted locally). |
M | Modified: File content differs between local and remote. |
R | Renamed: File was renamed (requires --find-renames or -M flag). |
T | Type Changed: File type changed (e.g., symlink to regular file). |
U | Unmerged: File has merge conflicts (needs resolution). |
X | Unknown: Git cannot determine the change type. |
Example: Detecting Renames#
By default, git diff may not detect renames. Use -M (or --find-renames) to identify renamed files:
git diff --name-status -M main origin/main Output example:
R100 src/old-name.js src/new-name.js # R100 = 100% rename similarity
Step 4: Advanced Comparisons#
Compare Specific Files/Directories#
To narrow results to a specific file or directory, append the path to the git diff command:
-
Specific file:
git diff --name-status main origin/main src/app.js -
Specific directory:
git diff --name-status main origin/main tests/
Compare Commit Ranges#
To list changes between two specific commits (instead of entire branches), use commit hashes:
git diff --name-status <commit-hash-1> <commit-hash-2> Example: Compare the last 3 local commits with the remote:
git diff --name-status HEAD~3 origin/main List Changes with Commit Details#
To see which commits introduced changes, use git log with --name-status:
git log --name-status origin/main..main origin/main..main: Shows commits inmainthat are not inorigin/main(local changes not pushed).
Output example:
commit a1b2c3d4 (HEAD -> main)
Author: Your Name <[email protected]>
Date: Wed Oct 11 12:00:00 2023
Update user guide
M docs/user-guide.md
commit e5f6g7h8
Author: Your Name <[email protected]>
Date: Tue Oct 10 10:30:00 2023
Add new feature
A src/new-file.txt
D tests/old-test.js
Step 5: Handling Detached HEAD or Stashed Changes#
Detached HEAD State#
If you’re in a detached HEAD state (not on a branch), compare your current commit directly with the remote:
git diff --name-status <current-commit-hash> origin/main Stashed Changes#
To compare stashed changes with the remote:
git diff --name-status stash@{0} origin/main stash@{0}: The most recent stash (usegit stash listto view all stashes).
Troubleshooting Common Issues#
"No Differences Found" When Changes Exist#
- Cause: You forgot to
git fetchthe remote, soorigin/mainis outdated. - Fix: Run
git fetch originand retry the comparison.
"fatal: ambiguous argument 'origin/main': unknown revision or path"#
- Cause: The remote branch name may differ (e.g.,
origin/masterinstead oforigin/main). - Fix: Check remote branches with
git branch -r, then use the correct name:git branch -r # Lists remote-tracking branches (e.g., origin/main, origin/feature-x) git diff --name-status main origin/master # If remote uses "master"
"Permission Denied" When Fetching#
- Cause: Invalid credentials or network issues.
- Fix: Verify remote URL with
git remote -v, check credentials (e.g., SSH keys, PATs), or ensure VPN/proxy settings allow access.
Conclusion#
Comparing local and remote Git repositories is a foundational skill for tracking changes and collaborating effectively. By following these steps:
- Fetch remote updates with
git fetch origin. - Use
git diff --name-status <local-branch> origin/<remote-branch>to list changed files. - Interpret status codes (A, M, D, etc.) to identify new, modified, or deleted files.
- Use advanced flags (e.g.,
-M,--find-renames) or path filters for granular control.
You’ll gain clarity on how your local work differs from the remote, reducing merge conflicts and ensuring smooth collaboration.