git应该删除空目录吗? [英] Is git supposed to delete empty directories?

查看:92
本文介绍了git应该删除空目录吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近对目录中的最后一个文件进行了git rm (a),由于某种原因,它决定删除该目录.我用一个新文件测试了行为,如下所示:

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

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

由于在上面的第一步之后没有抱怨,所以没有跟踪文件的目录的创建,为什么仅仅因为我从目录中删除了最后一个跟踪文件而删除目录?

>

关于它的价值,我正在运行版本2.7.4.


(a)我有一个带有gitDummy文件的占位符目录,以便将其推送到存储库中.然后,我有很多要添加的 real 文件,因此我删除了虚拟对象,然后尝试将其复制到新文件中,以准备添加,提交和推送.

瞧,由于目录已消失,复制操作失败.我怀疑如果我将文件复制到之前删除该虚拟对象的话,它会起作用,但是仍然让我感到奇怪的是,Git在不关心目录时会删除目录.

解决方案

git rm bug"

TLDR;这不是错误.

从提交X移到Y时,任何Git命令的行为都不应使树保持某种状态,如果重新克隆,则不会获得相同的Y.

进入线程:

概述

"git rm"将删除比指定数量更多的文件.这是错误或未记录的行为(手册页中没有).

设置

  1. 在git存储库中,创建一个空目录或一个空目录链

    $ mkdir -p path/to/some/

  2. 在最深的目录中创建一个文件,并将其添加到跟踪中

    $ touch path/to/some/file $ git添加路径/到/一些/文件 $ git commit -m'添加路径/到/某些/文件'

臭虫

在跟踪的文件上运行"git rm".

预期行为

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

请注意,path/path/to/path/to/some/仍然存在.

实际行为

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

尽管git仅输出"rm 'path/to/some/file'",但整个空目录链已删除.

仅在删除跟踪文件后链中的所有目录都为空时才会发生.

此行为未在手册页中记录.

我建议将'rmdir'语句添加到'git rm'输出中,或者更新手册页以反映此行为.

一般原则是:

Git无法跟踪空目录.
由于这是整个层次结构中的 only 内容,因此必须删除整个层次结构.

d9b814cc97 以来,这种行为似乎已经存在了很多年. (添加内置的"git rm"命令,2006-05-19,Git v1.4.0-rc1).
有趣的是,Linus在提交消息中指出,删除前导目录与git-rm是shell脚本时不同.
他想知道是否值得选择控制 这种行为.

我想大多数用户要么想要当前的行为 或他们很少碰到这一点,并感到惊讶,因为 git rm长期以来一直这样工作.

它与Git删除文件的其他部分也是一致的.例如., "git checkout"到没有文件的状态将删除 前导目录(当然,如果它们为空).

更一般地:

我将保持逆势而固执,并建议当前的行为还可以,因为对于任何其他行为都没有令人信服的理由.

始终,挂在空目录上的每道防线都将失效 直到将来我可能会做一些希望这些目录存在的事情."
好吧,如果是这样,那么就在需要它们时创建它们-您所做的任何事情都不应简单地假设基本目录的存在.

此外,通过取消跟踪"这些目录,您建议 Git安静地执行"git rm --cached"通常应执行的操作.
如果我想要这种行为,我宁愿自己键入.

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

其他人说了为什么,但是这可能是您可能没有的一个极端案例 想到:

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

如果您只有空目录"git status",则不会报告任何内容, 尽管"git clean -dxfn"将显示将要清除的内容.

因此,如果这如您所建议的那样起作用,则有人可以git rm一些 文件,那么所有内容都会报告它们正在提交XYZ,但是如果在该提交处将它们重新克隆,则会得到一棵看起来不同的树.

任何Git命令的行为都不应将树留在 状态从提交X->Y移出时,您将得到的Y不会相同 您重新克隆了.


注意:官方 git rm对Git存储库本身的测试(git/git/t/t3600-rm.sh)很明确:

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

I recently did a git rm of the last file in a directory(a) and, for some reason, it decided to delete the directory as well. I tested the behaviour with a new file as follows:

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

When I do that last line, the newdir directory disappears altogether. Is that expected behaviour? My understanding was that Git tracked files, not directories.

Since it doesn't complain after step one above, the creation of a directory with no tracked files, why is it deleting a directory just because I remove the last tracked file from it?

For what it's worth, I'm running version 2.7.4.


(a) I had a single placeholder directory with a gitDummy file so that it was pushed to the repo. I then had a whole lot of real files that I wanted to add so I removed the dummy then tried to copy in the new files in preparation for adding, committing and pushing.

Lo and behold, the copy operation failed because the directory had gone. I suspect it would have worked if I'd copied in the files before deleting the dummy but it still strikes me as strange that Git removes directories when it shouldn't care about them.

解决方案

This is followed in this June 2018 thread, where it is reported as a "git rm bug"

TLDR; it is not a bug.

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

On to the thread:

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.

The general principle is:

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).

More generally:

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.

For example, to illustrate why not deleting empty folder would be problematic:

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.


Note: the official git rm test (git/git/t/t3600-rm.sh) of the Git repo itself is quite clear as to what it expects:

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应该删除空目录吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆