3299

My initial commit contained some log files. I've added *log to my .gitignore, and now I want to remove the log files from my repository.

git rm mylogfile.log

will remove a file from the repository, but will also remove it from the local file system.

How can I remove this file from the repo without deleting my local copy of the file?

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
mveerman
  • 33,863
  • 3
  • 19
  • 14
  • 4
    Duplicate of [Stop tracking and ignore changes to a file in Git](http://stackoverflow.com/questions/936249/stop-tracking-and-ignore-changes-to-a-file-in-git) –  May 24 '14 at 23:21
  • 27
    It's worth noting that the most upvoted answer is dangerous for some. If you are using a remote repo than when you push your local then pull elsewhere those files you removed from git only *WILL BE DELETED*. This is mentioned in one of the replies but not commented upon. – RichieHH Aug 24 '18 at 04:17
  • to do it the right way: https://stackoverflow.com/questions/57418769/definitive-retroactive-gitignore-how-to-make-git-completely-retroactively-forg/ – goofology Aug 11 '20 at 19:35

11 Answers11

4699

From the man file:

When --cached is given, the staged content has to match either the tip of the branch or the file on disk, allowing the file to be removed from just the index.

So, for a single file:

git rm --cached mylogfile.log

and for a single directory:

git rm --cached -r mydirectory
Sam
  • 3,997
  • 4
  • 36
  • 61
bdonlan
  • 205,037
  • 27
  • 244
  • 316
  • 165
    Easily missed because it is not as self explanatory as `svn rm --keep-local`. – Martin Jun 24 '11 at 11:44
  • 125
    But how do I preserve the files on remote servers? This keeps my local one, but if I push and pull from another server, the file gets deleted. I also added a .gitignore for the file, but it still get's removed – spankmaster79 Feb 22 '13 at 15:44
  • 10
    This still removes the files on `git pull` if you are behind the commit after `git rm` – Petr Peller May 22 '14 at 17:02
  • 3
    Maybe instead of `git rm --cached mylogfile.log` it should be `git rm --unstage mylogfile.log` for more clearance. – sobi3ch Feb 21 '15 at 14:52
  • 3
    By switching to other branch, file is removed. – Vladimir Vukanac Jul 07 '16 at 10:05
  • 11
    Worth noting that, after running the command in the answer, you need to use `git commit -m "Commit message"` and `git push`. If you have any other staged changes (check with `git status`), they will also be committed at this time. – Sinjai Sep 11 '17 at 20:29
  • 16
    Since this is the most accepted answer and doesn't do, what is asked for, i'll tell what I do. I use the command `git rm --cached mylogfile.log` and delete the file from the repository. To avoid losing the file on productive system i do a backup of the file and pull after this. The file get's deleted as mentioned before and need to be copied back from your backup. This is quite a pain, but i found no better solution for this problem. – Marcel Grolms Dec 14 '17 at 18:37
  • 2
    For those that have missed in the question that the OP already added to .gitignore, please note that that's a necessary step to make sure the local file isn't deleted during a later merge or pull. You might find this answer helpful as well: https://stackoverflow.com/a/32182114/1024735 – kevinmicke Aug 14 '19 at 20:41
  • 2
    Wow, the language in that man page entry is super convoluted. -- I could have read it three times and not realized that it was related to this topic. – BrainSlugs83 Aug 24 '20 at 10:16
  • 1
    @BrainSlugs83 That's git for ya! – Kerry Johnson Sep 22 '20 at 16:59
295

To remove an entire folder from the repo (like Resharper files), do this:

git rm -r --cached folderName

I had committed some resharper files, and did not want those to persist for other project users.

konsolenfreddy
  • 9,296
  • 23
  • 36
Sam Tyson
  • 4,239
  • 4
  • 23
  • 33
  • 13
    Just an added note for future visitors: Don't use a GUI to "Sync" the commit back to the repo. That will pull the files back down into your local repo. You have to do a `Git Push repo branch` to actually remove the files from the remote. – RubberDuck Dec 04 '14 at 04:24
229

You can also remove files from the repository based on your .gitignore without deleting them from the local file system :

git rm --cached `git ls-files -i -X .gitignore`

Or, alternatively, on Windows Powershell:

git rm --cached $(git ls-files -i -X .gitignore)
Bruno Brant
  • 7,558
  • 5
  • 40
  • 76
null
  • 3,195
  • 1
  • 17
  • 27
  • 7
    Does not work on Windows. git ls-files -i -X .gitignore works, but I dont know how to send the files to 'git rm'. Do you know how to do that? – Erik Z May 09 '14 at 06:04
  • 17
    Works on Windows if you use Git Bash instead of cmd-console – Andreas Zita Dec 16 '14 at 18:12
  • 17
    Love this. Worked except that I had some files that ended up having spaces in filename. I modified solution here to this: `git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}"`. Please consider modifying or adding this solution to the answer here, because it is a great tool to have... – mpettis Mar 12 '16 at 17:48
  • 1
    I didn't try but it should be tested will it remove also files like `.gitkeep` which preserves an empty folder in repository. Eg. `.gitignore` contain folder `uploads` and repo is forced to keep track of `.gitkeep`. By removing all from repo under `uploads` it will remove also `.gitkeep`. – Vladimir Vukanac Jul 07 '16 at 09:11
  • 2
    This suggestion worked perfectly in powershell: git rm --cached $(git ls-files -i -X .gitignore) – geekandglitter Apr 21 '19 at 11:30
  • If the `.gitignore` in subdirectories shall be evaluated as well, use `--exclude-per-directory` instead of `-X`. – Samufi Apr 23 '20 at 20:28
  • In CMD, use a for: `for /f %x in ('git ls-files -i -X .gitignore') do git rm --cached %x` – B.McKee May 02 '20 at 19:11
108

As per my Answer here: https://stackoverflow.com/questions/6313126/how-to-remove-a-directory-in-my-github-repository

To remove folder/directory or file only from git repository and not from the local try 3 simple steps.


Steps to remove directory

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

Steps to ignore that folder in next commits

To ignore that folder from next commits make one file in root named .gitignore and put that folders name into it. You can put as many as you want

.gitignore file will be look like this

/FolderName

remove directory

Community
  • 1
  • 1
Suresh Karia
  • 14,742
  • 18
  • 63
  • 83
73

Also, if you have commited sensitive data (e.g. a file containing passwords), you should completely delete it from the history of the repository. Here's a guide explaining how to do that: http://help.github.com/remove-sensitive-data/

BoD
  • 10,222
  • 6
  • 60
  • 57
72

A more generic solution:

  1. Edit .gitignore file.

    echo mylogfile.log >> .gitignore

  2. Remove all items from index.

    git rm -r -f --cached .

  3. Rebuild index.

    git add .

  4. Make new commit

    git commit -m "Removed mylogfile.log"

Math Bob
  • 103
  • 1
  • 4
mAsT3RpEE
  • 1,650
  • 1
  • 16
  • 14
  • 2
    Will this actually delete the file ? – Mr_and_Mrs_D Dec 13 '13 at 15:39
  • 6
    From GitHub? NO. If you have already pushed to github it will not remove it from the site. But it will update your local git repository. – mAsT3RpEE Dec 14 '13 at 12:37
  • 6
    The comment you deleted was more eliminated actually :) The problem with the solution `rm --cashed` is that it will eventually delete the file when one pulls - right ? And this is not what people want when they say "Remove a file from the repository _without deleting it from the local filesystem_". Now why was the solution above accepted is beyond me - probably the OP was working alone and never pulled ? Dunno. I understand the github "once pushed always there" issue ofc – Mr_and_Mrs_D Dec 14 '13 at 12:42
  • I don't think there is a 100% solution unless you ask github itself. For now stick to this. Copy file, Add to gitignore, do actual git rm -r, commit, push, restore file. Did you manage to find another solution? – mAsT3RpEE Dec 14 '13 at 12:58
  • 11
    My problem is not github - it is that _the file will actually be deleted from coworkers when they pull_. I _don't_ want the file to be deleted. This has caused me huge issues in the past. So I was wondering if there is really a solution that really _does not_ delete the file. See also the comment inn the accepted answer : http://stackoverflow.com/questions/1143796/git-remove-a-file-from-the-repository-without-deleting-it-from-the-local-filesy/20565682?noredirect=1#comment21117138_1143800 – Mr_and_Mrs_D Dec 14 '13 at 13:07
  • Sorry man. I'm stumped. Option 1. inlude a download script that adds files after a pull. Option 2. Configure `git update-index --assume-unchanged` instead of `git rm`. – mAsT3RpEE Dec 14 '13 at 13:23
  • Since I'm terrified about destroying data, this answer would be better if it explicitly said whether or not mylogfile.log will be deleted locally at any of those steps. – Wyck Mar 10 '21 at 17:04
26

Git lets you ignore those files by assuming they are unchanged. This is done by running the git update-index --assume-unchanged path/to/file.txt command. Once marking a file as such, git will completely ignore any changes on that file; they will not show up when running git status or git diff, nor will they ever be committed.

(From https://help.github.com/articles/ignoring-files)

Hence, not deleting it, but ignoring changes to it forever. I think this only works locally, so co-workers can still see changes to it unless they run the same command as above. (Still need to verify this though.)

Note: This isn't answering the question directly, but is based on follow up questions in the comments of the other answers.

Rystraum
  • 1,750
  • 1
  • 17
  • 31
  • 3
    Hm, I do this but I see that the file can be overwritten if someone else makes changes to it on the repo. – AlxVallejo Sep 15 '14 at 16:50
24

If you want to just untrack a file and not delete from local and remote repo then use this command:

git update-index --assume-unchanged  file_name_with_path
Afraz Ahmad
  • 4,066
  • 23
  • 32
  • 4
    While this is a good answer, it's important to note this doesn't "untrack" a file in the sense that people usually use that word with Git, where an untracked file is one that isn't in the repository history and never has been. What this answer does is keep the file in the repository but prevent Git from noticing that changes have been made to it. That has some significant differences -- most importantly, the file is still present for others, and if someone else makes changes to it and you pull, your local copy can be overwritten without confirmation. – Soren Bjornstad Oct 22 '19 at 14:02
8

Above answers didn't work for me. I used filter-branch to remove all committed files.

Remove a file from a git repository with:

git filter-branch --tree-filter 'rm  file'

Remove a folder from a git repository with:

git filter-branch --tree-filter 'rm -rf directory'

This removes the directory or file from all the commits.

You can specify a commit by using:

git filter-branch --tree-filter 'rm -rf directory' HEAD

Or an range:

git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

To push everything to remote, you can do:

git push origin master --force
Samuel Philipp
  • 9,552
  • 12
  • 27
  • 45
Martijn Mellens
  • 524
  • 7
  • 23
  • 2
    This combined with `git rm -r --cached NAME` is the trick to remove it from your local git repo and prevent it from affecting anyone who pulls later (by deleting history of the file or directory from git.) – notbad.jpeg Mar 17 '16 at 20:15
  • 1
    This rewrites git history and you would need to push --force after, this is a bit out of scope with the question I guess. On a public famous repo you can't just change the history line like that as everyone having already cloned the repo would get issues when pulling. – Guillaume Perrot Apr 01 '17 at 01:37
  • From the man page "git filter-branch has a plethora of pitfalls .... Please use an alternative history filtering tool such as git filter-repo". Also, if you are going to rewrite history, I guess you could modify the ignore file at an early age so that the removed item(s) are ignored throughout the new history? – Rodney Feb 25 '21 at 05:20
0

This depends on what you mean by 'remove' from git. :)

You can unstage a file using git rm --cached see for more details. When you unstage something, it means that it is no longer tracked, but this does not remove the file from previous commits.

If you want to do more than unstage the file, for example to remove sensitive data from all previous commits you will want to look into filtering the branch using tools like the BFG Repo-Cleaner.

Dharman
  • 21,838
  • 18
  • 57
  • 107
Zach
  • 826
  • 3
  • 14
-1

Ignore the files, remove the files from git, update git (for the removal).

Note : this does not deal with history for sensitive information.

This process definitely takes some undertanding of what is going on with git. Over time, having gained that, I've learned to do processes such as:

1) Ignore the files

  • Add or update the project .gitignore to ignore them - in many cases such as yours, the parent directory, e.g. log/ will be the regex to use.
  • commit and push that .gitignore file change (not sure if push needed mind you, no harm if done).

2) Remove the files from git (only).

  • Now remove the files from git (only) with git remove --cached some_dir/
  • Check that they still remain locally (they should!).

3) Add and commit that change (essentially this is a change to "add" deleting stuff, despite the otherwise confusing "add" command!)

  • git add .
  • git commit -m"removal"
Community
  • 1
  • 1
Michael Durrant
  • 84,444
  • 83
  • 284
  • 429
  • see this questions for details of why this is a bad answer: https://stackoverflow.com/questions/57418769/definitive-retroactive-gitignore-how-to-make-git-completely-retroactively-forg/ – Ilya Kolesnikov Mar 12 '21 at 07:36