Git 签出到外部工作树并删除已删除的文件

The*_*olf 4 git dvcs git-checkout

我们想要使用 Git 在我们的网络服务器上部署代码。因此,我们在生产服务器上初始化了一个裸存储库。每当我们发布新版本时,我们都会在网站的 DocumentRoot 中执行 git checkout:

git --work-tree=/path/to/webroot/ checkout -f master
Run Code Online (Sandbox Code Playgroud)

在 的子目录中webroot,有几个 Git 不跟踪的文件(缓存文件、用户上传的文件等)。当然,在执行签出时,Git 不能删除这些内容(到目前为止,这部分工作正常)。

然而,Git 也不会删除以前跟踪过但同时被删除的文件(例如,它们在开发过程中因为不再需要而被删除)。目前,此类文件在该过程中仍然存在checkout,从而导致“死”文件的数量稳步增加。有没有办法让 Git 在执行时删除此类文件checkout

编辑-重现步骤:

# create dirs and repos
cd /base/path
mkdir repo.git
mkdir target
cd repo.git && git init

# create, add and commit two files
touch test1.txt
touch test2.txt
git add test1.txt test2.txt
git commit -m testcommit

# checkout to target directory
git --work-tree=../target checkout master -f
# target directory now contains both files

# remove one file from file system and git repo, commit
rm test2.txt
git rm test2.txt
git commit -m deletecommit

# checkout to target again
git --work-tree=../target checkout master -f
# target still contains both files
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 6

\n

但是,Git 也不会删除之前跟踪但同时已删除的文件

\n
\n

是的,对于 Git 2.22(2019 年第 2 季度)和 来说git checkout --overlay,确实如此。
\n"git checkout --no-overlay " 可用于触发一种从树状结构中检查路径的新模式,该模式允许与当前索引和工作树中的路径规范匹配且不在树状结构中的路径。

\n

请参阅Thomas Gummerer提交的提交 e92aa0e(2019 年 2 月 4 日)、提交 1495ff7提交 091e04b(2019 年 1 月 8 日)和提交 b7033e7提交 5160fa0提交 6fdc205提交 536ec18提交 b702dd1提交 a0cc584(2018 年 12 月 20 日)tgummerer
\n建议人:Jonathan Nieder ( artagnon)
\n (由Junio C Hamano 合并 -- gitster--提交 7d0c1f4中,2019 年 3 月 7 日)

\n
\n

checkout: 介绍--{,no-}overlay选项

\n
\n
\n

目前 \' git checkout\' 被定义为覆盖操作,这意味着如果在 \' git checkout <tree-ish> -- [<pathspec>]\' 中索引中有一个与 匹配的条目<pathspec>,但该条目在 \n 中不存在<tree-ish>,则该条目不会被删除来自索引或\n工作树。

\n
\n
\n

引入一个新--{,no-}overlay选项,允许git checkout在非覆盖模式下使用 \' \',从而如果文件不存在<tree-ish>但匹配,则从工作树中删除文件<pathspec>

\n
\n
\n

请注意,\' git checkout -p <tree-ish> -- [<pathspec>]\' 已经以这种方式工作,因此修补模式不需要进行任何更改。
\n我们禁止 \' git checkout --overlay -p\' 以避免混淆希望\n能够以git checkout -p这种方式强制 \' \' 启用覆盖模式的用户。

\n
\n
\n

未跟踪的文件不受此更改的影响,因此“git checkout --no-overlay HEAD -- untracked\”不会从工作树中删除未跟踪的文件。
\n例如 \' git checkout --no-overlay HEAD -- dir/\' 不会删除 中所有未跟踪的文件dir/,而只是重置 git 已知的文件的状态。

\n
\n

然后你就有了一个新的git config设置

\n
\n
checkout.overlayMode:\n
Run Code Online (Sandbox Code Playgroud)\n
\n
\n

在默认覆盖模式下,git checkout永远不会从索引或工作树中删除文件。
\n设置checkout.overlayMode为 false 时,出现在索引和工作树中但未出现的文件<tree-ish>将被删除,以使它们匹配<tree-ish>完全匹配。

\n
\n
\n

带有通配符路径规范的“`git Restore/checkout --no-overlay”错误地删除了子目录中的匹配路径,该问题已在 Git 2.29(2020 年第 4 季度)中得到纠正。

\n

请参阅Ren\xc3\xa9 Scharfe ( )提交的 bfda204(2020 年 8 月 22 日)。\n (由Junio C Hamano 合并 -- --提交 c57afd7中,2020 年 8 月 31 日)rscharfe
gitster

\n
\n

checkout, restore:使路径规范递归

\n

报告人:Sergii Shkarnikov
\n初始测试人:Sergii Shkarnikov
\n帮助人:Jeff King
\n签署人:Ren\xc3\xa9 Scharfe

\n
\n
\n

git checkout赋予and ( man )的路径规范and 与(via和(via .git restoretree_entry_interestingread_tree_recursive)match_pathspecce_path_match)

\n

后者实际上仅支持递归匹配,无论路径规范标志“recursive”的值如何,此处未设置该标志。

\n

这会导致带有通配符的路径规范的不同匹配结果,并且可能导致在无覆盖模式下检出和恢复以删除条目而不是修改它们。

\n

为签出和恢复启用递归匹配以使匹配一致。

\n

从技术上讲,设置标志checkout_main()也会影响( man ),但由于该命令根本不接受路径规范,因此没有实际后果。git switch

\n
\n