Image of Git-RM Uses & Purpose | A No-Nonsense Git RM Tutorial

ADVERTISEMENT

Table of Contents

Introduction

Distributed version control systems (DVCS) allow us to track changes to files over time. They are an extremely powerful tool for software development and developer collaboration.

Git is by far the most popular distributed version control system and has become essential for software dev teams of all sizes, and even provides many benefits when working on solo programming projects.

When working with Git, you mostly use git add to tell Git about new file changes and git commit to save those changes in your Git repo. However, there are times when you need to tell Git to remove or delete a file from future tracking. This could be because you added or committed a file accidentally. Or maybe you refactored your codebase and no longer need specific files in your project structure.

In this article, we will focus on the git rm command, describe its usage, various options, and how it can help increase your Git productivity.

What is git rm?

The basic usage of the git rm command is git rm <filename.ext>. This command with no options will remove the file from Git's index and from your working directory.

"Git rm removes a file or a group of files from the index, or from the working tree and the index." -The git rm documentation

But, what exactly does this mean?

Let's explore what the "...from the working tree and the index" part means first. Let's say you have a git-tracked directory, with a file first_file.txt and this file has already been committed to the Git repository. Now if you run the command git rm first_file.txt and then run git status you will get:

> git rm first_file.txt
rm 'first_file.txt'

> git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    first_file.txt

This git status output shows that the file is not only deleted from your working directory but the file deletion has also been staged for your next commit. Once you make your next commit, Git will no longer track that file going forward.

Remember that during standard operations including git rm, Git doesn't delete old history. Therefore, you can always checkout previous versions of a file even after removing it with git rm.

Can Git rm Delete Untracked Files?

No, untracked files cannot be deleted or removed using the Git rm command since by definition, Git was never told to track an untracked file in the first place. If you try to run Git rm on an untracked file, Git will throw the error fatal: pathspec 'filename' did not match any files.

Using Git rm On Untracked Files that were Added and Removed

Let's further explore how Git's staging area is affected when adding new untracked files that are deleted before running git rm. In this case, since git add is used before git rm, git rm will not throw the previous error.

> touch second_file.txt
> git add second_file.txt
> rm second_file.txt

> git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   second_file.txt

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    second_file.txt

This output shows that since we added second_file.txt using git add, it still exists in staging index, even though it was deleted in the working directory. In this situation, it would have been easier to run git rm second_file.txt, since you'd usually want to delete the untracked file from both the working directory and staging index if you added it accidentally.

To sum it up, git rm removes files from both the staging index and the working directory simultaneously, or it removes files from only the staging index if the file was already deleted in the working directory. Git rm changes do not affect the git repository until these changes have been committed.

If an untracked file is added using git add, and then deleted using git rm, you don't need to commit the change since the file was never included in Git's commit history.

What is the Difference Between git rm and rm?

Git rm can delete files from the staging index and the working directory, but cannot delete files only from the working directory. This makes sense because you can already do this with the rm command in Unix/Linux. So, git rm is essentially a shortcut for running the rm command followed by git add, to add the changes to the staging index.

Git rm Options

Now let's discuss some useful options for the git rm command.

git rm -r: The -r option stands for recursive, and it is used to delete directories and folders recursively. This is the same as the rm -r Unix/Linux command.

git rm -f: If you try to delete a tracked file that contains uncommitted changes, git rm has a safety check which prevents you from doing so:

> git rm filename.ext
error: the following file has local modifications:
    filename.ext
(use --cached to keep the file, or -f to force removal)

As seen in Git's output -f or the --force option is used to delete files forcefully and bypass this safety check.

git rm -n: The -n or --dry-run option does a dry run and tells you what files will be deleted when you run git rm, without actually deleting any files. This can be especially useful when deleting multiple files.

git rm --cached: The --cached option only removes files from the staging index and doesn't affect files in the working directory.

git rm -q: The -q or --quiet option runs the command but hides the output of the command.

git rm --ignore-unmatch: In Unix, if a command executes successfully it returns a 0 sigterm status, and not 0 otherwise. The --ignore-unmatch option will return a 0 even if the git rm fails to find a matched file and doesn't execute successfully. This can be useful when you are executing git rm in a shell script and want it to execute gracefully.

git rm --: The -- is an option used to separate options and a list of filenames.

More Git rm Examples

Let's say you have a folder dir1, running the git rm dir1 will return (similar to the regular rm command): fatal: not removing 'dir1' recursively without -r.

This tells you that you have to use the -r option when deleting directories. So you have to run the command:

> git rm -r dir1
rm 'dir1/file_a'
rm 'dir1/file_b'
rm 'dir1/file_c'

It outputs all the files that were removed with the command. Since a directory can have many files, it can be helpful to perform a dry run (-n option) of the git rm command, before actually running it. You can do so by:

> git rm -rn dir1
rm 'dir1/file_a'
rm 'dir1/file_b'
rm 'dir1/file_c'

This command still outputs all the files that will be deleted if the command were to run, but no files are actually deleted in the Git rm dry run.

Next, let's say you have a tracked file named first_file.txt which you made local changes to, but have not yet staged for commit:

> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   first_file.txt

no changes added to commit (use "git add" and/or "git commit -a")

If you realize you don't need the changes or the file at all, you might try to run the command git rm first_file.txt to remove the file. But you will face this error:

error: the following file has local modifications:
    first_file.txt
(use --cached to keep the file, or -f to force removal)

You can forcefully remove this file with the -f option and bypass the safety check like git rm -f first_file.txt.

You should be cautious when using the -f, --force option, because any uncommitted changes you made in the file would be lost once you run the command, with no way to recover them.

Next, let's say you wanted to remove the tracked file first_file.txt from the staging index, but keep it in the working directory. This will essentially convert the tracked file to an untracked file. You can do so with the --cached option:

> git rm --cached first_file.txt
> git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    first_file.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	first_file.txt

Here, you can see that this file has been deleted from the staging index, but git status also shows that first_file.txt is an untracked file, which means it's still present in the working directory.

You can see that git rm has a nice set of options to help improve your development efficiency.

How to Undo Git rm?

There might be a time when you accidentally delete a file with git rm. Thankfully if you have not yet committed the changes reverting the deletion can be pretty easy. Let's say you deleted a file first_file.txt with git rm:

  1. First, you can undo the changes to the staging area with the git reset command git reset HEAD.
  2. Next, you must undo the changes in your working directory by checking out that file git checkout first_file.txt.

This combination will basically tell Git to reset its state to the last commit and then checkout the version of the deleted file from that commit.

If you delete multiple files, you can use the git checkout . command, which will undo changes to the entire current directory. If you have no important changes in your working directory or staging area, you can use the git reset --hard HEAD command. This will update everything to commit specified by Git HEAD. But, you should be extremely cautious when using this command, as it discards uncommitted changes in the working directory and staging index.

Summary

In this article, you learned how to use the git rm command and its options to maximize your productivity when removing files in Git.

First, you learned what git rm does by understanding its definition with examples. Next, you went over the difference between git rm and rm in Unix/Linux. Then, you went over all the options you can use with git rm and more git rm examples using those options. Finally, you learned various ways to undo git rm.

Next Steps

If you're interested in learning more about how Git works under the hood, check out our Baby Git Guidebook for Developers, which dives into Git's code in an accessible way. We wrote it for curious developers to learn how Git works at the code level. To do this we documented the first version of Git's code and discuss it in detail.

We hope you enjoyed this post! Feel free to shoot me an email at jacob@initialcommit.io with any questions or comments.

References

  1. Git Documentation https://git-scm.com/docs/git-rm

Final Notes