git - git 应该删除空目录吗?

标签 git

我最近对目录(a) 中的最后一个文件执行了git rm 操作,出于某种原因,它决定也删除该目录。我使用如下新文件测试了该行为:

mkdir newdir
touch newdir/newfile
git add newdir/newfile
git commit
git rm newdir/newfile

当我执行最后一行时,newdir 目录完全消失了。这是预期的行为吗?我的理解是 Git 跟踪文件,而不是目录。

既然在上面的第一步创建没有跟踪文件的目录后它没有提示,为什么它删除目录只是因为我从中删除了最后一个跟踪文件?

不管怎样,我运行的是 2.7.4 版。


(a) 我有一个带有 gitDummy 文件的占位符目录,因此它被推送到 repo。然后我有一大堆想要添加的真实文件,所以我删除了虚拟文件,然后尝试复制新文件,为添加、提交和推送做准备。

你瞧,复制操作失败了,因为目录已经消失了。我怀疑如果我在删除虚拟文件之前复制到文件中它会起作用,但它仍然让我感到奇怪,因为 Git 在它不应该关心它们时删除了目录。

最佳答案

2022 年:

这应该不再是 Git 2.35 (Q1 2022) 的问题

不再有“严重:无法读取当前工作目录:没有这样的文件或目录


2019:原答案:

June 2018 thread 紧随其后,它被报告为“git rm bug

长长的;这不是错误。

当从提交 X 移动到 Y 时,任何 Git 命令的行为都不应该让树处于这样一种状态,你不会得到相同的 Y 如果你重新克隆。

进入主题:

OVERVIEW

"git rm" will remove more files than specified. This is either a bug or undocumented behavior (not in the man pages).

SETUP

  1. In a git repository, create an empty directory OR a chain of empty directories

    $ mkdir -p path/to/some/

  2. Create a file in the deepest directory and add it to tracking

    $ touch path/to/some/file $ git add path/to/some/file $ git commit -m 'add path/to/some/file'

THE BUG

Run 'git rm' on the tracked file.

EXPECTED BEHAVIOR

$ git rm path/to/some/file
rm 'path/to/some/file'
$ ls path
to/
$ ls path/to
some/

Note that path/, path/to/, and path/to/some/ still exist.

ACTUAL BEHAVIOR

$ git rm path/to/some/file
rm 'path/to/some/file'
$ ls path
ls: cannot access 'path': No such file or directory

The entire chain of empty directories is removed, despite the fact the git outputs only "rm 'path/to/some/file'".

This ONLY occurs when all the directories in the chain are empty after the tracked file has been removed.

This behavior is NOT documented in the man pages.

I propose that 'rmdir' statements are added to 'git rm' output, or that the man pages be updated to reflect this behavior.

一般原则是:

Git cannot track empty directories.
As that was the only content in that whole hierarchy, the entire hierarchy had to be deleted.

It looks like this behavior has been in place for many years, since d9b814cc97 ("Add builtin "git rm" command", 2006-05-19, Git v1.4.0-rc1).
Interestingly, Linus noted in the commit message that the removal of leading directories was different than when git-rm was a shell script.
And he wondered if it might be worth having an option to control that behavior.

I imagine that most users either want the current behavior or they rarely run across this and are surprised, given how long git rm has worked this way.

It's also consistent with other parts of Git that remove files. E.g., "git checkout" to a state that does not have the file will remove the leading directories (if they're empty, of course).

更一般地说:

I am going to be contrarian and obstinate and suggest that the current behaviour is fine, since there is no compelling rationale for any other behaviour.

Invariably, every defense for hanging on to empty directories boils down to, "I might do something in the future that expects those directories to exist."
Well, if that's the case, then create them when you need them -- nothing you do should ever simply assume the existence of essential directories.

In addition, by "untracking" those directories, you're suggesting that Git quietly do what should normally be done by "git rm --cached".
If I want that behaviour, I would prefer to have to type it myself.

例如,为了说明为什么删除空文件夹会有问题:

Others have said why, but here's an edge case you probably haven't thought of:

(
   rm -rf /tmp/repo &&
   git init /tmp/repo &&
   cd /tmp/repo &&
   mkdir -p foo/bar/baz &&
   git status
)

If you just have empty directories "git status" will report nothing, although "git clean -dxfn" will show what would be cleaned up.

So if this worked as you're suggesting then someone could git rm some file, then everything would report that they're on commit XYZ, but if they re-cloned at that commit they'd get a tree that would look different.

No Git command should behave in such a way as to leave the tree in a state when moving from commit X->Y that you wouldn't get the same Y if you re-cloned.


注:官方git rm test (git/git/t/t3600-rm.sh) Git 存储库本身非常清楚它的期望:

test_expect_success 'rm removes subdirectories recursively' '
    mkdir -p dir/subdir/subsubdir &&
    echo content >dir/subdir/subsubdir/file &&
    git add dir/subdir/subsubdir/file &&
    git rm -f dir/subdir/subsubdir/file &&
    ! test -d dir

关于git - git 应该删除空目录吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55486848/

相关文章:

git - 在 docker 容器中获取代理后面的 git

Git 克隆到另一个现有的 Git 仓库

git - docker.exe:无效的引用格式:存储库名称必须为小写

git - git 的 master 分支应该包含什么

git - 使用 Git 进行原子网站更新

git - 配置 TortoiseGitPlink 自动加载特定 URL 的 key

git - 在 Heroku 上克隆以前的版本

git - 在 Bitbucket 管道中增加一个数字

xcode - 如何删除github仓库的内容?

c# - NGit 中查看远程仓库是否更改的方法是什么?