BACKEND2025-01-05📖 5 min read

How to Remove Files from a Remote Git Repository

How to Remove Files from a Remote Git Repository

A step-by-step guide to safely removing unwanted files from a remote Git repository, covering tracked vs. untracked files and how to use .gitignore effectively.

髙木 晃宏

代表 / エンジニア

👨‍💼

Most developers have been there: a file that never should have been version-controlled somehow ends up in the remote repository. Whether it's a .env file, build artifacts, or IDE configuration files, accidentally pushing something leaves you wondering how to clean it up. This article walks through the concrete steps to safely remove unwanted files from a remote Git repository, along with practical tips from real-world experience.

Understanding the Difference Between Tracked and Untracked Files

Getting a clear picture of how Git categorizes files is the essential first step. Git divides files into two main states: tracked and untracked.

Tracked files are files that have previously been staged with git add and recorded in at least one commit. Git actively monitors these files for changes and includes them in diff detection and staging operations.

Untracked files, on the other hand, exist in the working directory but are not under Git's management. They show up as "Untracked files" in git status output, so distinguishing them isn't difficult.

The key thing to understand here is that .gitignore patterns only apply to untracked files. Files that are already tracked will not be ignored even if you add them to .gitignore. This is a surprisingly easy detail to miss — I've personally been caught off guard by it, wondering why changes to .gitignore weren't having any effect. You're not alone if this has tripped you up too.

Step-by-Step: Removing Unwanted Files from the Remote Repository

There are several approaches to removing unwanted files from a remote repository. Choosing the right one depends on your situation.

Method 1: Remove the file entirely with git rm

If you don't need the file locally or remotely, this is the simplest approach.

git rm path/to/unnecessary-file.log git commit -m "Remove unnecessary file" git push origin main

This command deletes the file from both the working directory and the repository. Add the -r flag if you need to remove an entire directory.

Method 2: Remove from remote only with git rm --cached

For cases where you want to keep the file locally but remove it from the remote — such as local configuration files — the --cached option is the right tool.

git rm --cached path/to/config.local git commit -m "Stop tracking local config file" git push origin main

The --cached flag removes the file only from Git's index (the staging area), leaving the file intact on your local filesystem. In my experience, this is the most frequently used approach in day-to-day work.

To handle a directory, use the recursive flag:

git rm --cached -r node_modules/ git commit -m "Stop tracking node_modules" git push origin main

Method 3: Bulk-remove multiple files at once

If you've updated your .gitignore mid-project, you may want to untrack everything that should now be ignored in one go.

git rm --cached -r . git add . git commit -m "Rebuild tracked files based on updated .gitignore" git push origin main

This clears the entire index and rebuilds it, ensuring your .gitignore rules take full effect. Be aware that the resulting diff will be large — if you're working in a team, it's worth giving everyone a heads-up first. The first time I ran this I was briefly alarmed by the size of the diff, but since the actual file contents don't change, reviewing it with a calm eye will reassure you that everything is in order.

Preventing Recurrence with .gitignore

Removing a file after the fact is treating the symptom. The real fix is setting up .gitignore properly so the same files never sneak back into the repository.

The golden rule: always pair a file removal with an update to .gitignore.

# 1. Update .gitignore echo "*.log" >> .gitignore echo ".env" >> .gitignore # 2. Untrack the files git rm --cached *.log .env # 3. Commit everything together git add .gitignore git commit -m "Untrack unnecessary files and update .gitignore" git push origin main

Ideally, .gitignore is configured at the start of a project — but in practice, it's common to realize gaps only after development is underway. GitHub's gitignore template collection covers a wide range of languages and frameworks and is an excellent reference when starting a new project.

You can also configure a global .gitignore to automatically exclude OS-specific files like .DS_Store or Thumbs.db across all your repositories:

git config --global core.excludesfile ~/.gitignore_global

This one-time setup meaningfully reduces the risk of accidentally committing files you never intended to track.

Special Considerations for Files Containing Sensitive Data

The steps above are sufficient for general unwanted files, but if a file containing sensitive information — such as API keys or passwords — has been pushed to a remote repository, a more careful response is required.

Running git rm only removes the file from the latest commit. The file remains accessible in past commit history, and anyone who can access the repository can retrieve it by browsing the history. This is a risk that's easy to overlook.

If you need to scrub the file from the entire history, consider tools like git filter-branch or the faster BFG Repo-Cleaner.

# Example using BFG Repo-Cleaner java -jar bfg.jar --delete-files .env git reflog expire --expire=now --all git gc --prune=now --aggressive git push origin --force

Note that --force push rewrites the remote history, so all team members must be notified before you proceed. More importantly, treat any credentials that were ever exposed as compromised, regardless of whether you've cleaned the history. Rotate the affected keys and passwords — revoke them and issue new ones. No tool alone fully solves this problem.

Summary: Build Good Habits Before Problems Occur

To recap the approaches for removing files from a remote Git repository:

  • Don't need it locally or remotelygit rm for a complete removal
  • Need to keep it locallygit rm --cached to untrack without deleting
  • Prevent recurrence → Always pair removals with a .gitignore update
  • Sensitive data → Full history purge plus credential rotation are both required

The most effective long-term solution is to set up .gitignore at the start of a project and make git status checks part of your pre-commit routine. Fixing problems after they occur is always harder than preventing them in the first place — building these habits into your daily workflow pays off more than you'd expect.

If you're struggling with Git workflows or your team's development process, feel free to reach out to aduce. We're happy to work with you to find practical solutions tailored to your team's situation.