GIT检出除一个文件夹外的内容

23
我想要切换到另一个分支或先前的提交,但我希望保留一个文件夹中的相同文件(不要切换该文件夹)。
我希望该文件夹将显示在git status中,以便我现在可以将该文件夹添加到索引中。
例如,我有一个带有node_modules的文件夹。 我希望该文件夹出现在我的所有提交中(我知道大多数人喜欢.gitignore node_modules文件夹)。 但是当我移动到其他提交或切换到其他分支时,我希望git不会触及node_modules文件夹。
这是可能的吗?
4个回答

40

您可以使用稀疏检出(sparse checkout)功能从工作树中排除node_modules目录的提交内容。如文档中所述:

“稀疏检出”允许稀疏地填充工作目录。 它使用skip-worktree位告诉Git是否值得查看工作目录中的文件。

以下是如何使用它的步骤。首先,启用sparseCheckout选项:

git config core.sparseCheckout true

然后,您需要在.git/info/sparse-checkout文件中将 node_modules 路径作为否定项添加:

echo -e "/*\n!node_modules" >> .git/info/sparse-checkout

这将创建一个名为sparse-checkout的文件,其中包含:

/*
!node_modules

这实际上意味着,在将提交的树读入工作目录时,忽略node_modules 目录

如果以后想要再次包含node_modules目录(即从其文件中删除skip-worktree位),则必须修改sparse-checkout文件,仅包含/* - 即“包括所有路径”,并使用git read-tree更新您的工作目录:

echo "/*" > .git/info/sparse-checkout
git read-tree -mu HEAD

您可以通过将其配置变量设置为false来完全禁用稀疏检出:

git config core.sparseCheckout false

请注意,稀疏检出最初是在Git 1.7.0中引入的。


谢谢!只是确认一下,如果有一天我从sparse-checkout文件中删除了node_modules,我是否可以正常返回过去,并查看它过去包含的内容?(我阅读了您发送的链接,但我不明白skip-worktree bit是什么意思...) - Aminadav Glickshtein
可以的。我更新了我的答案,包括如何重新引入 node_modules 目录并禁用稀疏检出。 - Enrico Campidoglio
非常有趣。我得去看看(不是git checkout),我需要测试一下 :) - Aminadav Glickshtein
作为澄清的一点,这将在单个文件名或名称上与在目录名称上的操作完全相同。 - Christopher Hunter
对于 echo 命令,也许应该使用单引号?我不确定是要责怪 ZSH、Ember 还是它们的组合,但是即使我执行 echo "/*\n!node_modules",我的 shell 扩展结果也会变成 echo "/*\nnode_modules/.bin/ember -v" - ken

2

为启用稀疏检出并检出除名为unwanted的目录或文件之外的所有内容:

git sparse-checkout set --no-cone '/*' '!unwanted'

禁用稀疏检出并检出所有内容:

git sparse-checkout disable

来源:《INTERNALS — FULL PATTERN SET》文档


0

我从我想要检出的分支中检出了整个代码

# assume we want the `components` folder on my-branch to follow us

# first checkout your code to (my-new-branch) for ex.
git checkout -b my-new-branch

# now i'm on my-new-branch (but it doesn't have the components from my-branch :| )

# delete ./components
rm -rf ./components 

# replace it with the one on my-branch :)
git checkout my-branch -- ./components 

祝你好运...


分支需要不断更新到主分支的任何更改,这很麻烦。read-tree 更接近作者的要求。 - holms

0

read-tree 稀疏检出 命令相比,git sparse-checkout 命令在锥形模式下提供了一种替代方法(此处介绍

在 Git 2.34 (Q4 2021) 版本中,在锥形模式下,稀疏索引代码路径学会了删除稀疏锥形外的被忽略文件(如构建产物),允许删除整个稀疏锥形外的目录。这在稀疏模式更改时特别有用。

请查看 commit 716f68e(2021年8月10日)由Junio C Hamano (gitster)提交。
请查看 commit 55dfcf9, commit ce7a9f0, commit 77efbb3, commit 02155c8, commit 8a96b9d, commit 5dc1675, commit 72d84ea, commit e27eab4, commit 522d3ce(2021年9月8日)由Derrick Stolee (derrickstolee)提交。
(由Junio C Hamano -- gitster --合并于commit dc89c34,2021年9月20日)

sparse-checkout:清除被追踪的稀疏目录

签名作者:Derrick Stolee
审核作者:Elijah Newren

当使用cone模式更改稀疏检出的范围时,我们可能会有一些已跟踪的目录超出范围。当前的逻辑会从这些目录中删除被跟踪的文件,但会保留这些目录中的被忽略文件。这对于向Git提供不再需要这些目录的用户来说有点意外。这是cone模式类型中的新内容:用户明确表示“我想要这些目录而不是那些目录”。典型的稀疏检出模式通常适用于“我想用这些模式文件”,因此自然而然地将忽略的文件保持原样。cone模式中对目录的关注为我们提供了改变行为的机会。
保留这些被忽略的文件在稀疏目录中,无法实现在稀疏索引中获得性能优势。当我们跟踪这些目录时,我们需要知道文件是否被忽略,这可能取决于稀疏目录内已跟踪的.gitignore文件。这取决于文件的索引版本,因此需要扩展稀疏目录。在删除它们之前,我们必须特别注意查找这些目录中未跟踪的、未忽略的文件。我们不想删除用户在这些目录中做的任何有意义的工作,也许是在切换稀疏检出定义之前忘记添加和提交的。由于这些未跟踪的文件可能是生成被忽略的构建输出的代码文件,在这种情况下也不要删除这些目录中的任何被忽略的文件。用户可以通过将其稀疏检出定义重置为包括该目录并继续来恢复其状态。或者,他们可以看到所呈现的警告,并自行删除目录以恢复他们期望的性能。
通过在更改范围时删除稀疏目录(或运行“git稀疏检出”重新应用),我们可以像仓库处于干净状态一样恢复这些性能优势。由于这些被忽略的文件经常是构建输出或来自IDE的助手文件,因此用户现在不需要这些文件了,因为已经删除了跟踪的文件。如果已跟踪的文件重新出现,则它们将具有比构建工件更新的时间戳,因此必须重新生成工件。使用稀疏索引作为数据结构,以便找到可以安全删除的稀疏目录。如果索引以前是完整的,请重新扩展索引。

git sparse-checkout现在在其手册页面中包含以下内容:

在锥形模式下更改稀疏检出模式时,Git将检查每个未在稀疏检出锥内的已跟踪目录,以查看它是否包含任何未跟踪的文件。如果所有这些文件都由于.gitignore模式而被忽略,则该目录将被删除。
如果该目录中有任何未跟踪的文件未被忽略,则该目录内不会发生任何删除操作,并显示警告消息。如果这些文件很重要,请重置您的稀疏检出定义以包括它们,使用git addgit commit将它们存储,然后手动删除任何剩余文件,以确保Git能够以最佳方式运行。


你能展示一下如何使用它的例子吗? - Aminadav Glickshtein
@AminadavGlickshtein 这个还在进行中:https://github.com/git/git/commit/716f68ec33e3506babee03c4df497a7e211220ee#diff-f0e9d5771c607d2b7d8151fe4d3a32142b262fab89c7751195599177b3632350R494 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接