98

I've got my repo @ github. I did some work at home and pushed it to github. It involved some deleting of files and directories. Now I'm on my work box, which had a copy of the code before deleting the files and directories.

I issued the following:

git remote update
git checkout HEAD
git pull origin HEAD

It deleted all of the files it should have, but not the directories the files were in.

Two questions:

  1. Why did it not remove the directories?
  2. Is there a git command I can issue in the current state to remove them?
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
mculp
  • 2,637
  • 1
  • 25
  • 34
  • Agreed, git checkout HEAD does nothing, since HEAD is a ref pointing to the currently checked-out commit. You probably were going for master in both cases. – Cascabel Sep 30 '09 at 17:52
  • Well, HEAD actually updated everything with the exception of deleting the empty directories. Like I said, I'm new to git. – mculp Sep 30 '09 at 18:13
  • Possible duplicate of [How do I force "git pull" to overwrite local files?](http://stackoverflow.com/questions/1125968/how-do-i-force-git-pull-to-overwrite-local-files) Please check the answers there if you still want some different solutions. – DrBeco Mar 31 '17 at 05:10

6 Answers6

175

Git doesn't track directories, so it won't remove ones that become empty as a result of a merge or other change. However, you can use git clean -fd to remove untracked directories (the -fd flag means force removal of untracked files and directories).

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 4
    I'm confused. Then why did the directories get deleted from my GitHub repo when I committed/pushed changes? – mculp Sep 30 '09 at 18:25
  • 2
    The directories in your working copy may have contained untracked files (including hidden untracked files), and thus they may appear to be empty but really aren't, so Git didn't remove them. `git clean` will, of course. – mipadi Sep 30 '09 at 18:37
  • Thanks for the command. That cleaned them out. However, I still don't understand why it deleted the directories on a commit/push but not on a checkout/pull. The directories contained no hidden or unhidden files. – mculp Sep 30 '09 at 18:43
  • 4
    It may have something to do with the fact that GitHub repos are _bare_ repositories (they don't have working copies), but your local one does. I imagine if you cloned a _new_ repo from the GitHub origin, you wouldn't have those directories. – mipadi Sep 30 '09 at 18:55
  • 27
    But of course, run the command with `-n` (dry run) instead of `-f` first, so you can see what is going to be deleted. Especially since `git clean -d` removes not _only_ those worisome directories, but also untracked files. – Todd Owen Jan 13 '12 at 08:16
  • GitHub doesn't use a working directory to show the webpages. It understands git repositories, so uses history and changeset data directly from the logs. – Lasse V. Karlsen Dec 05 '14 at 11:24
  • Running 'git clean -fd' will not satisfy your needs. Deleting all untracked files & directories will include those files/dirs that you've put in your .gitignore - probably not what you've meant. I don't see any fully automated and concise way to remove directories which became empty due to branch switches. Just a per environment customised hook might do the trick in this case. – Eli Golin Jun 20 '16 at 04:54
  • 2
    @EliGolin: `git clean` doesn't delete files listed in .gitignore unless you pass the `-x` option. – mipadi Jun 20 '16 at 19:50
  • This does not work for me on Windows 7. Git messages that it cannot remove the empty directory. – Argent Jan 13 '17 at 13:27
  • should be `git clean -nd` to do a dry run – tsando May 14 '19 at 15:01
  • I needed to add -x also, so it removes all untracked files. – Yogurtu Oct 20 '19 at 04:27
8

I had same issue, in my case on build service (CI).. as GIT pulls all files without cleaning folders, all the bin / obj that were previously builded by the CI are dirty, so If I remove a test project, the bin will still contain the DLL and will mention tests that does not exist.

In order to solve this issue; this command seems to do the trick (at least for me)

git clean -fd -x

where X will remove all untracked files:

-X Remove only files ignored by Git. This may be useful to rebuild everything from scratch, but keep manually created files.

Yogurtu
  • 2,656
  • 3
  • 23
  • 23
  • Be careful with this ... the `-x` cleared my logs which I did want ( locally on remote server, just not in Git ) but are ignored by `.gitignore` because they change often – Ricky Levi Jun 13 '23 at 11:54
4

As part of most operations that alter the working tree (pull, merge, checkout, etc.) git will remove any directories which are made empty by that operation (i.e. git removed the last file).

git won't remove any directories that aren't completely empty, so if you have hidden or ignored files then just because git removes the last tracked file from that directory doesn't necessarily mean that git will be able to remove that directory. git doesn't consider this to be an error condition so won't complain about it.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • My GitHub repo does not have the directories. When I committed, it removed the directories correctly. However, when I checkout/pull it removes only the files. The directories are empty. $ ls -al total 8 drwxr-xr-x 2 mculp mculp 4096 Sep 23 15:43 ./ drwxr-xr-x 8 mculp mculp 4096 Sep 30 10:51 ../ – mculp Sep 30 '09 at 18:10
  • 1
    I'm not quite sure what you mean by "switched HEAD to master", I presume you mean "`git checkout master`" but most people would just say "I switched to/checked out master". Anyway, when git said 'Already up-to-date.' it means that it didn't do anything. git will only remove directories that it *makes* empty. – CB Bailey Sep 30 '09 at 18:33
  • Bad wording. I changed "HEAD" to "master" as some people have suggested in the comments. – mculp Sep 30 '09 at 18:40
  • @CharlesBailey, what you said is not what I see. `git checkout` did not remove a completely empty directory. – Asclepius Oct 25 '13 at 18:22
  • @A-B-B: Git only removes directories that are _made_ empty by a checkout operation. I have tested this again; it still works. – CB Bailey Oct 26 '13 at 08:05
2

Git doesn't track directories, files (with their path). Git creates all the directories for those paths if they don't exist yet (cool!), however it does not delete them if all the files contained in a path are moved or deleted (not cool ☹ ... but there's reasons).

Solution (once you have pulled / fast-forwarded / merged):

git stash --include-untracked
git clean -fd
git stash pop

If you don't stash before clean, you will loose all your untracked files (irreversibly).

Note: since this cleans all ignored files too, you might need to run some of your build scripts again to recreate project metadata (ex: ./gradlew eclipse). This also delete directories that are empty and that were never part of paths of git files.

qwertzguy
  • 15,699
  • 9
  • 63
  • 66
0

For me, the directory was a submodule, so I needed to run -f twice:

git clean -f -f -d
Ricky Levi
  • 7,298
  • 1
  • 57
  • 65
-1

Git does not track directories currently (see git wiki), that is, you neither can add empty directories nor will git remove directories that end up empty. (EDIT: Thanks, Manni, I was wrong! You can't add empty directories, but git will remove directories that become empty because their tracked content was deleted.)

As to the command to remove the empty directories: that depends on your operating system.

For Linux you could use, e.g.,

find -depth -type d -empty -exec rmdir {} \;

However, this will remove all empty directories!

janko
  • 4,123
  • 28
  • 26
  • 1
    The wiki page says that git doesn't create empty directories for you. It does **not** say that it won't delete empty directories. What mculp wants works for me. – innaM Sep 30 '09 at 16:27
  • @janko, Actually, git failed to remove a completely empty directory for me. – Asclepius Oct 25 '13 at 18:24