Git checkout/pull不会删除目录?

100

我在 GitHub 上有一个代码库。我在家里做了一些工作并将其推送到 GitHub。它涉及删除一些文件和目录。现在我正在我的工作电脑上,这台电脑拥有在删除这些文件和目录之前的代码副本。

我执行了以下操作:

git remote update
git checkout HEAD
git pull origin HEAD

它删除了应该删除的所有文件,但没有删除文件所在的目录。

两个问题:

  1. 为什么它没有删除目录?
  2. 在当前状态下是否有可以使用的git命令来将它们删除?

同意,git checkout HEAD 不会做任何事情,因为 HEAD 是一个指向当前检出的提交的引用。你可能在两种情况下都想要主分支。 - Cascabel
好的,HEAD 实际上更新了所有内容,除了删除空目录。就像我说的,我对 git 还很新。 - mculp
可能是如何强制“git pull”覆盖本地文件?的重复问题。如果您仍然想要其他解决方案,请在那里检查答案。 - DrBeco
6个回答

176

Git不跟踪目录,因此它不会删除由于合并或其他更改而变为空的目录。然而,您可以使用git clean -fd来删除未跟踪的目录(-fd标志意味着强制删除未跟踪的文件和目录)。


4
我感到困惑。为什么当我提交/推送更改时,我的GitHub仓库中的目录被删除了? - mculp
2
你的工作副本中可能包含未跟踪文件(包括隐藏的未跟踪文件)的目录,因此它们可能看起来是空的,但实际上并不是,所以 Git 没有删除它们。当然,git clean可以做到。 - mipadi
4
可能与 GitHub 仓库是“裸”仓库有关(它们没有工作副本),而本地仓库有关。我想象如果你从 GitHub 源克隆了一个新的仓库,你就不会有那些目录。 - mipadi
27
当然,在运行命令时先使用-n(干跑)而不是-f,这样您就可以看到将要被删除的内容。特别是因为git clean -d不仅会删除令人担忧的目录,还会删除未被跟踪的文件。 - Todd Owen
2
@EliGolin:git clean 命令不会删除 .gitignore 文件中列出的文件,除非你使用 -x 选项。 - mipadi
显示剩余6条评论

8

我遇到了同样的问题,在我的构建服务(CI)上。因为GIT在不清理文件夹的情况下拉取所有文件,所以之前由CI构建的所有bin/obj都是脏的,因此如果我删除一个测试项目,bin仍将包含DLL并提到不存在的测试。

为了解决这个问题,这个命令似乎可以解决问题(至少对我来说是这样)。

git clean -fd -x

X会删除所有未跟踪的文件:

-X仅删除Git忽略的文件。这对于从头开始重建但保留手动创建的文件可能很有用。


小心处理这个问题... -x 命令清除了我的日志,虽然我不希望它们出现在 Git 中(只是本地远程服务器上),但是由于它们经常变动,所以被 .gitignore 忽略了。 - Ricky Levi

4

在大多数涉及更改工作目录的操作(如pull、merge、checkout等)中,Git会删除由该操作使得为空的任何目录(即Git删除了最后一个文件)。

如果您有隐藏或忽略的文件,那么仅仅因为Git从该目录中删除了最后一个已跟踪文件,并不意味着Git能够删除该目录,除非该目录完全为空。Git不认为这是错误条件,因此不会抱怨。


我的 GitHub 存储库没有目录。当我提交时,它正确地删除了目录。但是,当我 checkout/pull 时,它只删除文件。目录为空。$ ls -al 总用量 8 drwxr-xr-x 2 mculp mculp 4096 9月 23 15:43 ./ drwxr-xr-x 8 mculp mculp 4096 9月 30 10:51 ../ - mculp
1
我不太确定你所说的"switched HEAD to master"是什么意思,我猜你是指"git checkout master",但大多数人会直接说"我切换到了/检出了master分支"。无论如何,当git显示'Already up-to-date.'时,意味着它没有执行任何操作。git只会删除由它自己造成为空的目录。 - CB Bailey
措辞不当。我将“HEAD”更改为“master”,因为一些人在评论中建议这样做。 - mculp
@CharlesBailey,您所说的不是我所见到的。git checkout并没有删除一个完全空的目录。 - Asclepius
@A-B-B:Git 只会删除由 checkout 操作使得空的目录。我已经再次测试过,它仍然有效。 - CB Bailey

2

Git不会跟踪目录和文件(包括它们的路径)。如果这些路径不存在,Git会为它们创建所有目录(很棒!),但是如果一个路径中的所有文件被移动或删除,Git并不会删除它们(很糟糕☹ ...但是有原因)。

解决方案(一旦您已经拉取/快进/合并):

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

如果在执行clean之前不进行stash,你将会永久性地丢失所有未被跟踪的文件。

注意:由于此操作也会清除所有被忽略的文件,因此您可能需要重新运行一些构建脚本以重新创建项目元数据(例如:./gradlew eclipse)。此操作还会删除那些空的目录,并且这些目录从未出现在git文件路径中。


0
对我来说,该目录是一个子模块,所以我需要运行两次-f
git clean -f -f -d

-1

Git目前不跟踪目录(请参阅git wiki),也就是说,您既不能添加空目录,也不会删除最终变为空的目录。

(修改: 谢谢Manni, 我错了! 你不能添加空目录,但当它们被删除时git将删除目录)

至于删除空目录的命令:这取决于您的操作系统。

对于Linux,您可以使用例如:

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

然而,这将删除所有空目录!


1
维基页面说git不会为你创建空目录。它并没有说它不会删除空目录。Mculp想要的对我也有效。 - innaM
@janko,实际上,git无法为我删除一个完全空的目录。 - Asclepius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接