签出 Git 中的子目录?

发布于 2024-07-07 14:42:48 字数 593 浏览 10 评论 0原文

是否可以在 Git 中查看存储库的子目录?

想象一下我正在设置一个新的 WordPress 安装。 我将为我的插件和主题自定义创建两个新目录:

  • wordpress/wp-content/plugins/myplugins/
  • wordpress/wp-content/themes/mytheme/

我想要通过 Git 维护这些目录。 在 Subversion 中,我将通过拥有 trunk/myplugins/trunk/mytheme/ 目录并签出子目录来实现此目的。 Git 是否有办法使用单个存储库完成相同的任务?

作为一个很少接触 Git 的长期 SVN 用户,我可能只是错过了一些 Git 范例。

编辑:多个分支存储不同的内容是一个处理这个问题的有趣方法。

Is it possible to check out subdirectories of a repository in Git?

Imagine I am setting up a new WordPress installation. I will create two new directories for my plugin and theme customization:

  • wordpress/wp-content/plugins/myplugins/
  • wordpress/wp-content/themes/mytheme/

I want to maintain these directories via Git. In Subversion, I would accomplish this by having trunk/myplugins/ and trunk/mytheme/ directories and checking out subdirectories. Does Git have a way to accomplish the same task using a single repository?

I could just be missing the boat on some Git paradigm, as a long time SVN user with little exposure to Git.

Edit: Multiple branches storing different content is an interesting way to handle this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

千秋岁 2024-07-14 14:42:48

稀疏结账现在使用 Git 1.7

另请参阅问题“是否可以在不先检出整个存储库的情况下进行稀疏检出?”。

请注意,稀疏签出仍然需要您下载整个存储库,即使 Git 下载的某些文件最终不会出现在您的工作树中。

Sparse checkouts are now in Git 1.7.

Also see the question “Is it possible to do a sparse checkout without checking out the whole repository first?”.

Note that sparse checkouts still require you to download the whole repository, even though some of the files Git downloads won't end up in your working tree.

感性不性感 2024-07-14 14:42:48

git clone --filter + git稀疏-checkout 仅下载所需的文件

例如,仅克隆子目录 small/< 中的文件/code> 在此测试存储库中: https://github .com/cirosantilli/test-git-partial-clone-big-small-no-bigtree

git clone -n --depth=1 --filter=tree:0 \
  https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree
cd test-git-partial-clone-big-small-no-bigtree
git sparse-checkout set --no-cone small
git checkout

此选项是与远程协议的更新一起添加的,它确实可以防止从服务器下载对象。

我已在以下位置更详细地介绍了这一点: 如何仅克隆 Git 存储库的子目录?

已于 2021 年 1 月在 git 2.30.0 上进行测试。

git clone --filter + git sparse-checkout downloads only the required files

E.g., to clone only files in subdirectory small/ in this test repository: https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree

git clone -n --depth=1 --filter=tree:0 \
  https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree
cd test-git-partial-clone-big-small-no-bigtree
git sparse-checkout set --no-cone small
git checkout

This option was added together with an update to the remote protocol, and it truly prevents objects from being downloaded from the server.

I have covered this in more detail at: How do I clone a subdirectory only of a Git repository?

Tested on git 2.30.0 on January 2021.

喵星人汪星人 2024-07-14 14:42:48

在 git 中没有真正的方法可以做到这一点。 如果您不会进行同时影响两个树作为单个工作单元的更改,则没有充分的理由为两个树使用单个存储库。 我以为我会错过这个 Subversion 功能,但我发现创建存储库的管理心理开销非常小(仅仅是因为存储库存储在其工作副本旁边,而不是要求我明确选择存储库之外的某个位置)工作副本),我习惯于制作大量小型的单一用途存储库。

不过,如果您坚持(或确实需要),您可以创建一个仅包含 mythememyplugins 目录的 git 存储库,并在 WordPress 安装中对它们进行符号链接。


MDCore 写道:

提交例如mytheme将增加myplugin的修订号

请注意,如果您决定将两个目录放在一个目录中,这不是 git 关心的问题存储库,因为 git 完全消除了任何形式的单调递增修订号的概念。

git 中将哪些内容放在单个存储库中的唯一标准是它是否构成单个单元,即。 在您的情况下,是否存在单独查看每个目录中的编辑没有意义的更改。 如果您需要同时编辑两个目录中的文件并且编辑内容属于同一目录,那么它们应该是一个存储库。 如果没有,那就不要把它们混在一起。

Git 确实希望您为不同的实体使用单独的存储库。

子模块

子模块不能满足将两个目录保留在一个存储库中的愿望,因为它们实际上会强制每个目录都有一个单独的存储库,然后使用子模块将它们汇集到另一个存储库中。 更糟糕的是,由于 WordPress 安装中的目录不是同一目录的直接子目录,而且也是包含许多其他文件的层次结构的一部分,因此使用每个目录存储库作为统一存储库中的子模块不会带来任何好处,因为统一的存储库不会提供任何好处。存储库不会反映任何用例/需求。

There is no real way to do that in git. And if you won’t be making changes that affect both trees at once as a single work unit, there is no good reason to use a single repository for both. I thought I would miss this Subversion feature, but I found that creating repositories has so little administrative mental overhead (simply due to the fact that repositories are stored right next to their working copy, rather than requiring me to explicitly pick some place outside of the working copy) that I got used to just making lots of small single-purpose repositories.

If you insist (or really need it), though, you could make a git repository with just mytheme and myplugins directories and symlink those from within the WordPress install.


MDCore wrote:

making a commit to, e.g., mytheme will increment the revision number for myplugin

Note that this is not a concern for git, if you do decide to put both directories in a single repository, because git does away entirely with the concept of monotonically increasing revision numbers of any form.

The sole criterion for what things to put together in a single repository in git is whether it constitutes a single unit, ie. in your case whether there are changes where it does not make sense to look at the edits in each directory in isolation. If you have changes where you need to edit files in both directories at once and the edits belong together, they should be one repository. If not, then don’t glom them together.

Git really really wants you to use separate repositories for separate entities.

submodules

Submodules do not address the desire to keep both directories in one repository, because they would actually enforce having a separate repository for each directory, which are then brought together in another repository using submodules. Worse, since the directories inside the WordPress install are not direct subdirectories of the same directory and are also part of a hierarchy with many other files, using the per-directory repositories as submodules in a unified repository would offer no benefit whatsoever, because the unified repository would not reflect any use case/need.

我不吻晚风 2024-07-14 14:42:48

我不喜欢稀疏签出的一件事是,如果您想签出几个目录深的子目录,您的目录结构必须包含通向它的所有目录。

我解决此问题的方法是将存储库克隆到不是我的工作区的位置,然后在我的工作区目录中创建到存储库中的子目录的符号链接。 Git 的工作方式非常好,因为像 git status 这样的东西会显示相对于当前工作目录的更改文件。

One thing I don't like about sparse checkouts, is that if you want to checkout a subdirectory that is a few directories deep, your directory structure must contain all directories leading to it.

How I work around this is to clone the repo in a place that is not my workspace and then create a symbolic link in my workspace directory to the subdirectory in the repository. Git works like this quite nicely because things like git status will display the change files relative to your current working directory.

聊慰 2024-07-14 14:42:48

事实上,“窄”或“部分”或“稀疏”签出目前正在为 Git 进行大量开发。 请注意,您仍然在 .git 下拥有完整的存储库。 因此,另外两篇文章是当前 Git 状态的最新文章,但看起来我们最终将能够进行稀疏签出。 如果您对更多详细信息感兴趣,查看邮件列表 --他们正在迅速变化。

Actually, "narrow" or "partial" or "sparse" checkouts are under current, heavy development for Git. Note, you'll still have the full repository under .git. So, the other two posts are current for the current state of Git but it looks like we will be able to do sparse checkouts eventually. Checkout the mailing lists if you're interested in more details -- they're changing rapidly.

南冥有猫 2024-07-14 14:42:48

正如您的编辑所指出的,您可以使用两个单独的分支来存储两个单独的目录。 这确实将它们保留在同一个存储库中,但您仍然无法跨两个目录树进行提交。 如果您对一个目录的更改需要对另一个目录进行更改,则必须将它们作为两个单独的提交来执行,并且您打开了两个目录的一对检出可能不同步的可能性。

如果您想将这对目录视为一个单元,您可以使用“wordpress/wp-content”作为存储库的根目录,并在顶层使用 .gitignore 文件来忽略除感兴趣的两个子目录之外的所有内容。 这可能是目前最合理的解决方案。

据称,稀疏检查已经出现两年了,但在 git 开发仓库中仍然没有任何迹象,也没有任何迹象表明必要的更改将会到达那里。 我不会指望他们。

As your edit points out, you can use two separate branches to store the two separate directories. This does keep them both in the same repository, but you still can't have commits spanning both directory trees. If you have a change in one that requires a change in the other, you'll have to do those as two separate commits, and you open up the possibility that a pair of checkouts of the two directories can go out of sync.

If you want to treat the pair of directories as one unit, you can use 'wordpress/wp-content' as the root of your repo and use .gitignore file at the top level to ignore everything but the two subdirectories of interest. This is probably the most reasonable solution at this point.

Sparse checkouts have been allegedly coming for two years now, but there's still no sign of them in the git development repo, nor any indication that the necessary changes will ever arrive there. I wouldn't count on them.

二智少女 2024-07-14 14:42:48

您无法签出存储库的单个目录,因为整个存储库是由项目根目录中的单个 .git 文件夹处理的,而不是 subversion 的无数 .svn 目录。

在单个存储库中处理插件的问题是,提交例如 mytheme 会增加 myplugin 的修订号,因此即使在 subversion 中也最好使用单独的存储库。

子项目的颠覆范例是 svn:externals ,它有点翻译到 git 中的 子模块 (但不完全是在你使用过 svn 的情况下:之前的外部。)

You can't checkout a single directory of a repository because the entire repository is handled by the single .git folder in the root of the project instead of subversion's myriad of .svn directories.

The problem with working on plugins in a single repository is that making a commit to, e.g., mytheme will increment the revision number for myplugin, so even in subversion it is better to use separate repositories.

The subversion paradigm for sub-projects is svn:externals which translates somewhat to submodules in git (but not exactly in case you've used svn:externals before.)

天邊彩虹 2024-07-14 14:42:48

这里有一个灵感。 只需使用 shell regexgit regex

git checkout commit_id */*.bat  # *.bat in 1-depth subdir exclude current dir, shell regex  
git checkout commit_id '*.bat'  # *.bat in all subdir include current dir, git regex

使用引号转义 shell 正则表达式解释并将通配符传递给 git。

第一个是不是递归的,仅是 1 深度 subdir 中的文件。 但第二个是递归的。

对于您的情况,以下内容可能就足够了。

git checkout master */*/wp-content/*/*
git checkout master '*/wp-content/*'

只需根据需要修改线路即可。

There is an inspiration here. Just utilize shell regex or git regex.

git checkout commit_id */*.bat  # *.bat in 1-depth subdir exclude current dir, shell regex  
git checkout commit_id '*.bat'  # *.bat in all subdir include current dir, git regex

Use quotation to escape shell regex interpretation and pass wildcards to git.

The first one is not recursive, only files in 1-depth subdir. But the second one is recursive.

As for your situation, the following may be enough.

git checkout master */*/wp-content/*/*
git checkout master '*/wp-content/*'

Just hack the lines as required.

水染的天色ゝ 2024-07-14 14:42:48

我查看了不同的响应,包括来自 How我是否只克隆 Git 存储库的子目录?

它们并不是非常简单的答案,因此我决定编写一个小型 shell 脚本来帮助简化该过程。
请参阅 https://gist.github.com/hiranp/a26e334369386211709f4846929a6157

#!/bin/env bash

# This script clones the remote repository using the --filter=blob:none option to avoid downloading any file contents. 
#   It then checks out the specified remote branch and enables sparse-checkout. The sparse-checkout pattern is set to only 
#   include the desired folder, and finally, the latest changes are pulled from the remote branch.

# NOTE: 
# Customize this script by setting the REMOTE_REPO_URL, REMOTE_BRANCH, GIT_FOLDER_PATH, and LOCAL_REPO_PATH variables.

# Set the remote repository URL
REMOTE_REPO_URL="<URL>"

# Set the remote branch name
REMOTE_BRANCH="branch-name"

# Set the path to the folder you want to copy
GIT_FOLDER_PATH="path/to/folder"

# Set the path to the local repository
LOCAL_REPO_PATH="path/to/local/repo"

echo "Cloning the remote repository...to ${LOCAL_REPO_PATH}"
if [ ! -d "${LOCAL_REPO_PATH}" ]; then
    mkdir -p "${LOCAL_REPO_PATH}"
    # Shadow clone the remote repository
    git clone --depth 1 --no-checkout --filter=blob:none "${REMOTE_REPO_URL}" "${LOCAL_REPO_PATH}"
fi

# Change to the repository directory
cd "${LOCAL_REPO_PATH}"

# Checkout the remote branch
git checkout "${REMOTE_BRANCH}"

if [ ! -f ".git/info/sparse-checkout" ]; then
    # Enable sparse-checkout
    git sparse-checkout init

    # Set the sparse-checkout pattern to only include the desired folder
    git sparse-checkout set "${LOCAL_REPO_PATH}"
fi

# Pull the latest changes from the remote branch
git pull origin "${REMOTE_BRANCH}"

I looked at the different response including ones from How do I clone a subdirectory only of a Git repository?

They weren't very simple answers, so I decided to write a small shell script that should help simplify the process.
See https://gist.github.com/hiranp/a26e334369386211709f4846929a6157

#!/bin/env bash

# This script clones the remote repository using the --filter=blob:none option to avoid downloading any file contents. 
#   It then checks out the specified remote branch and enables sparse-checkout. The sparse-checkout pattern is set to only 
#   include the desired folder, and finally, the latest changes are pulled from the remote branch.

# NOTE: 
# Customize this script by setting the REMOTE_REPO_URL, REMOTE_BRANCH, GIT_FOLDER_PATH, and LOCAL_REPO_PATH variables.

# Set the remote repository URL
REMOTE_REPO_URL="<URL>"

# Set the remote branch name
REMOTE_BRANCH="branch-name"

# Set the path to the folder you want to copy
GIT_FOLDER_PATH="path/to/folder"

# Set the path to the local repository
LOCAL_REPO_PATH="path/to/local/repo"

echo "Cloning the remote repository...to ${LOCAL_REPO_PATH}"
if [ ! -d "${LOCAL_REPO_PATH}" ]; then
    mkdir -p "${LOCAL_REPO_PATH}"
    # Shadow clone the remote repository
    git clone --depth 1 --no-checkout --filter=blob:none "${REMOTE_REPO_URL}" "${LOCAL_REPO_PATH}"
fi

# Change to the repository directory
cd "${LOCAL_REPO_PATH}"

# Checkout the remote branch
git checkout "${REMOTE_BRANCH}"

if [ ! -f ".git/info/sparse-checkout" ]; then
    # Enable sparse-checkout
    git sparse-checkout init

    # Set the sparse-checkout pattern to only include the desired folder
    git sparse-checkout set "${LOCAL_REPO_PATH}"
fi

# Pull the latest changes from the remote branch
git pull origin "${REMOTE_BRANCH}"
一刻暧昧 2024-07-14 14:42:48

您可以仅恢复对特定文件或目录的未提交更改:

git checkout [some_dir|file.txt]

You can revert uncommitted changes only to particular file or directory:

git checkout [some_dir|file.txt]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文