我在使用git clean时遇到了问题,并排除了嵌套目录的选项。
我想从repo中清除所有未提交的文件,不包括vendor/bundle
目录。
我的测试报告喜欢:
debugg-dir/
.git/
file.txt
not-commited-file
not-commited-folder
another-not-commited-file
vendor/
bundle/
another-not-commited-file
重现测试回购:
git init debugg-dir && cd debugg-dir
touch file.txt && g a . && git ci -m "Commit"
mkdir -p not-commited-folder && touch not-commited-folder/another-not-commited-file
mkdir -p vendor/bundle && touch vendor/bundle/another-not-commited-file && touch not-commited-file
Git clean命令:
git clean -d -x -n -e vendor/bundle
清洁后预计有:
debugg-dir/
.git/
file.txt
vendor/
bundle/
another-not-commited-file
有没有正确的方法从git clean命令中排除嵌套的dir?
#编辑:
解释
这种情况没有“干净”的解决方案。
Git clean用git clean -d -x -n -e dir_name
排除dirs,但这不适用于嵌套目录。
这是git中的错误还是有一些很好的理由?更多信息为什么这不起作用你可以找到in source。长话短说,排除模式仅适用于字符串,直到模式中的第一个'/'。
我的解决方案:
cd vendor && git clean -dxf -e bundle && cd ..
git clean -dxf -e vendor
有了这个我设法只保留嵌套的目录和它的内容。
答案 0 :(得分:1)
这是因为vendor
是一个未跟踪的目录,您使用的是- d
选项。
正如the manual所说:
-d
除了未跟踪的文件外,还删除未跟踪的目录。如果未跟踪的目录由不同的git存储库管理,则默认情况下不会删除它。如果你真的想删除这样的目录,请使用-f选项两次。
我可以使用此命令获得所需的输出:
git clean -x -n
这在真实场景中有效吗?如果没有,您可能希望在vendor/bundle
中提交其他文件,然后查看。
答案 1 :(得分:1)
根据git clean --help
git-clean - 从工作树中删除未跟踪的文件
如果您添加Floyd Pink关于-d
的解释(很快,该选项也允许删除未跟踪的目录而不仅仅是文件),那么这也是您删除vendor
的原因。<登记/>
现在,据说你只想删除我认为你应该not-commited-file
(所以,没有任何未跟踪的目录也没有another-not-commited-file
)git clean
交互模式,所以
git clean -i
会询问您如何为每个未跟踪的文件做些什么(只有文件,如果您也想要提供目录,请添加 -d
。)
<登记/>
OP编辑问题后编辑:您也想删除目录,因此请运行
git clean -i -d
编辑2 :由于-e
的含义在手册中并不清楚,我用Google搜索并找到了this。我建议阅读对话,因为它解释了-e
的真正含义,而不是OP的意图(或者可以从手册中理解)
编辑3 ,更多关于-e
切换。根据我在编辑2 中找到的链接,我决定尝试一下。结果,我希望这将有助于您理解-e
内容.gitignore
,所以我不提交临时文件:
*.tmp
我发出了命令:
echo "Temporary file" > sample.tmp
git st //which of course shows *nothing to commit, working directory clean*
git clean -fX -e \!sample.tmp
结果是删除了具有tmp扩展名的所有文件(由于-X
)但是sample.tmp
。所以,总而言之,-e
真正做了什么,在我的理解中,如果我错了,请纠正我,不要排除清洁过程中的模式,但
从清除规则中排除模式(在我的情况下,规则是删除所有.tmp文件,我从中手动排除了sample.tmp)。
答案 2 :(得分:1)
这是我用来清理git repos的代码,同时排除了venv/
目录和子目录:
git clean -nXd -e \!venv -e \!venv/**
对于您来说,第一个排除就足够了:
git clean -nXd -e \!vendor
第二个排除项\!venv/**
适用于.gitignore中的其他规则,这些规则可能适用于供应商内部的文件或文件夹。例如:
.gitignore
*.log
vendor/
bundle/
another-not-commited-file.log
答案 3 :(得分:0)
Git 2.24(2019年第四季度)使git clean在嵌套Git 存储库(不仅是文件夹)方面更加强大
请参见commit 69f272b(2019年10月1日)以及commit 902b90c,commit ca8b539,commit 09487f2,commit e86bbcf,commit 3aca580,{{3} },commit 29b577b,commit 89a1f4a,commit a3d89d8,commit 404ebce,commit a5e916c,commit bbbb6b0(由commit 7541cc5)(2019年9月17日)。< br />
(由Elijah Newren (newren
)在Junio C Hamano -- gitster
--中合并,2019年10月11日)
clean
:避免在嵌套的Git存储库中删除未跟踪的文件用户希望嵌套git存储库中的文件可以单独放置,除非有足够的强制(带有两个
-f
)。不幸的是,在某些情况下,git会删除嵌套存储库中的跟踪文件(可能是脏文件)和未跟踪文件。
为解释这种情况是如何发生的,我们来比较一下两种情况。
首先,采用以下示例设置(假设我们已经在git repo中):
git init nested
cd nested
>tracked
git add tracked
git commit -m init
>untracked
cd ..
在此设置中,一切正常。运行“
git clean -fd
”将导致fill_directory()
返回以下路径:
nested/
nested/tracked
nested/untracked
然后
correct_untracked_entries()
会注意到可以将其压缩为:
nested/
然后由于“
nested/
”是目录,因此我们将调用remove_dirs("nested/", ...)
,它将检查is_nonbare_repository_dir()
然后决定跳过它。但是,如果有人还创建了一个忽略的文件:
>nested/ignored
然后运行“
git clean -fd
”将导致fill_directory()
返回 相同的路径:
nested/
nested/tracked
nested/untracked
但是
correct_untracked_entries()
会注意到我们已经忽略了条目 在nested /下,因此可以简化此列表为
nested/tracked
nested/untracked
由于这些不是目录,因此我们没有
call remove_dirs()
,这是唯一经过is_nonbare_repository_dir()
安全检查的地方,这导致我们同时删除了未跟踪的文件和被跟踪的文件(并且可能很脏)文件。此问题的一种可能的解决方法是遍历每个路径的父目录,并检查它们是否代表非裸存储库,但这很浪费。
即使我们添加了某种形式的缓存,也仍然很浪费,因为我们甚至应该首先进入“ nested /”就可以代表一个非裸存储库。
在DIR_SKIP_NESTED_GIT
上添加dir_struct.flags
标志,并使用它来防止fill_directory()
和朋友进入嵌套的git repos。通过此更改,我们还修改了commit aafb754中添加的两个回归测试(“
t7300
:添加测试以记录干净和嵌套git的行为”,2015-06-15,Git v2.6.0 -rc0)。
那个提交,它的系列,或者邮件列表上该系列的前六个迭代都讨论了为什么这些测试编码了他们的期望。
实际上,看来他们的目的只是为了测试现有行为,以确保性能变化不会改变行为。
但是,这两个测试直接与联机帮助页上的说法相矛盾,该手册页声称需要两个-f
来删除嵌套git存储库下的文件/目录。
尽管有人可能会说用户给出了一条与嵌套存储库中的文件/目录相匹配的显式路径,但是一旦您沿着这条路线走,用户就会很难理解它的滑坡(例如,如果他们指定了“ {{ 1}}“?)
也很难解释确切的行为是什么。通过使其变得非常简单来避免此类问题。最后,仍然存在一些错误,其中
git clean -f -d '*.c'
清理不充分(例如,缺少嵌套的-ffd
),而.git
可能清理了错误的文件(注意外部-ffdX
而非内部)。
此修补程序根本无法解决这些情况(并且不会更改相对于这些标志的行为),仅在给定单个.gitignore
时修复了处理。
有关-f
错误的更多讨论,请参见commit 91479b9。