我最近对目录中的最后一个文件做了git rm
{sup>(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在不关心目录时会删除目录。
答案 0 :(得分:8)
在此June 2018 thread之后,它被报告为“ git rm bug
”
从提交X
移至Y
时,任何Git命令的行为都不应使树保持在某种状态,如果您这样做,您将不会得到相同的Y
重新克隆。
进入线程:
概述
“
git rm
”将删除比指定数量更多的文件。这是错误或未记录的行为(手册页中没有)。设置
在git存储库中,创建一个空目录或一个空目录链
$ mkdir -p path / to / some /
在最深的目录中创建一个文件并将其添加到跟踪中
$ 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回购本身的官方git rm
test (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