【发布时间】:2016-03-11 00:36:42
【问题描述】:
我习惯了rcs。签入后,我通常会执行rcsclean 来删除所有存在的跟踪罚款,以便目录中只存在 untracked 文件。我有时会执行 rcsclean -u 来撤消对跟踪文件的任何更改。
我如何在 git 中做到这一点?
之后,当前目录及其子目录中应该只有未跟踪的文件(当然 .git 存储库本身除外)。
【问题讨论】:
标签: git version-control rcs
我习惯了rcs。签入后,我通常会执行rcsclean 来删除所有存在的跟踪罚款,以便目录中只存在 untracked 文件。我有时会执行 rcsclean -u 来撤消对跟踪文件的任何更改。
我如何在 git 中做到这一点?
之后,当前目录及其子目录中应该只有未跟踪的文件(当然 .git 存储库本身除外)。
【问题讨论】:
标签: git version-control rcs
Git 不是 RCS。你可以做你想做的事,但如果你试图将 Git 存储库视为一个基于文件的修订控制系统,你将会给自己带来长期的痛苦。
您可以删除 Git 正在跟踪的文件,但是具有更大/更深目录树的项目将需要您采取额外步骤来删除空目录(Git 不会将其作为一流对象进行跟踪),并且您将失去执行 git commit -a 之类的操作的能力,而 Git 不会认为您正在删除所有文件。
您可以使用 ls-files 子命令删除 Git 知道的所有文件。您需要将输出通过管道传输到 xargs,因为 rm 命令本身不能处理以 null 结尾的字符串,并且像“foo bar/baz quux”这样的路径没有它们会导致问题。
要删除所有提交给 Git 的文件:
$ git ls-files -z | xargs -0 -- rm -f
然而,Git 并不真正跟踪目录;它跟踪树。因此,除非您将所有文件都放在项目的根目录中,否则您需要自己将 空目录 作为单独的命令删除,如果您希望它们也消失的话。例如:
$ find . -type d -empty -not -path '*.git*'
完成此操作后,您需要避免使用像 git commit -a 这样的命令,该命令会将所有丢失的文件视为已删除。相反,您必须更加小心地暂存文件。您可能还想调查man git-update-index 并考虑--assume-unchanged 标志是否会帮助您或使情况变得更糟。
此外,git status 命令将继续显示大量更改,因为您已从工作树中删除了文件。如果您从工作树中“清理”了大量文件,则git status 之类的命令的输出可能会变得如此混乱,以至于如果不进行过滤就变得毫无用处。例如,要查找真正未被跟踪而不是删除或修改的文件:
$ git status -su | fgrep '??'
?? bar
?? wibble
【讨论】:
Git 和 RCS 有不同的用例。想要清除你的 Git 工作树是非常不寻常的,所以我假设这是一个 X/Y 问题,你试图查看哪些文件当前未跟踪。
为此有一个内置的 Git 命令:git status --untracked-files。此命令的默认模式是 all,而 git status(不带标志)的输出默认为 normal。详情请见man 1 git-status。
mkdir -p foo/bar/baz
touch foo/quux foo/bar/wibble
git status -u
On branch master Untracked files: (use "git add <file>..." to include in what will be committed) foo/bar/wibble foo/quux nothing added to commit but untracked files present (use "git add" to track)
请注意,此输出中永远不会显示没有文件的目录树。这是因为 Git 不会跟踪目录,除非是作为树对象的一部分,因此此示例中的 foo/bar/baz 永远不会显示为未跟踪,除非文件(又名目录条目)存在于 baz 中或目录树。
换句话说,要使 baz 显示为未跟踪,baz 中必须有一个文件,或者 baz 的子目录必须包含一个文件。例如,使用--short 标志以获得更简洁的输出:
$ touch foo/bar/baz/file; git status -s -u
?? foo/bar/baz/file
?? foo/bar/wibble
?? foo/quux
将在输出中包含foo/bar/baz/file。人们经常为此目的使用空的隐藏文件,例如 .gitkeep。
【讨论】: