Git 1.7.0 中的稀疏结帐?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2336580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sparse checkout in Git 1.7.0?
提问by davr
With the new sparse checkout featurein Git 1.7.0, is it possible to just get the contents of a subdirectory like how you can in SVN? I found this example, but it preserves the full directory structure. Imagine that I just wanted the contents of the 'perl' directory, without an actual directory named 'perl'.
使用Git 1.7.0 中新的稀疏结帐功能,是否可以像在 SVN 中那样只获取子目录的内容?我找到了这个例子,但它保留了完整的目录结构。想象一下,我只想要“perl”目录的内容,而没有名为“perl”的实际目录。
-- EDIT --
- 编辑 -
Example:
例子:
My git repository contains the following paths
我的 git 存储库包含以下路径
repo/.git/
repo/perl/
repo/perl/script1.pl
repo/perl/script2.pl
repo/images/
repo/images/image1.jpg
repo/images/image2.jpg
repo/doc/
repo/doc/readme.txt
repo/doc/help.txt
What I want is to be able to produce from the above repository this layout:
我想要的是能够从上面的存储库中生成这个布局:
repo/.git/
repo/script1.pl
repo/script2.pl
However with the current sparse checkout feature, it seems like it is only possible to get
但是,使用当前的稀疏结帐功能,似乎只能获得
repo/.git/
repo/perl/script1.pl
repo/perl/script2.pl
which is NOT what I want.
这不是我想要的。
回答by richq
You still need to clone the whole repository, which will have all the files. You could use the --depth
flag to only retrieve a limited amount of history.
您仍然需要克隆整个存储库,其中将包含所有文件。您可以使用该--depth
标志仅检索有限数量的历史记录。
Once the repository is cloned, the read-tree trick limits your "view" of the repository to only those files or directories that are in the .git/info/sparse-checkout
file.
一旦存储库被克隆,读取树技巧将您对存储库的“视图”限制为仅文件中的那些文件或目录.git/info/sparse-checkout
。
I wrote a quick script to help manage the sparseness, since at the moment it is a bit unfriendly:
我写了一个快速脚本来帮助管理稀疏性,因为目前它有点不友好:
#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD
If you save this script as git-sparse.sh
into the path reported by calling git --exec-path
, then you can run git sparse foo/ bar/
to only "checkout" the foo and bar directories, or git sparse '*'
to get everything back again.
如果您将此脚本另存为git-sparse.sh
通过调用报告的路径git --exec-path
,则您可以运行git sparse foo/ bar/
以仅“检出” foo 和 bar 目录,或者git sparse '*'
重新获取所有内容。
回答by John K
The short answer is no. Git sees all files as a single unit.
最简洁的答案是不。Git 将所有文件视为一个单元。
What I recommend is that you break down you repositories into logical chunks. A separate one for perl, images, and docs. If you also needed to maintain the uber repo style you can create a repo made up of Submodules.
我建议您将存储库分解为逻辑块。一个单独的 perl、图像和文档。如果您还需要维护 uber 回购风格,您可以创建一个由Submodules组成的回购。
回答by PhilYoussef
richq's answer was close, but it missed a step. You need to explicitly enable sparse checkout:
Richq 的回答很接近,但它错过了一步。您需要显式启用稀疏结帐:
git config core.sparsecheckout true
git config core.sparsecheckout 真
This blog post has all the steps outlined clearly:
这篇博文清楚地列出了所有步骤:
回答by Ger4ish
Now without plunging into detail about why would you want to do this, your problem can be (probably) easily solved by a symlink/shortcut.
现在无需详细说明您为什么要这样做,您的问题可以(可能)通过符号链接/快捷方式轻松解决。
To answer the question - no, and with a meaningful reason. The whole history of the repo is downloaded even with a 'sparse checkout'. To clarify why this is necessary - otherwise tracking renamed files would be a pain in the ...neck. Imagine you move the file /repo_root/asd/file1.cpp
to /repo_root/fgh/file1.cpp
- now if you had only downloaded /repo_root/fgh
deltas, you won't know about file1.cpp. So this means you must download all deltas. But then you have a full repository; not just a folder cut of it, therefore just the /rero_root/fgh
folder is not a repo itself. This might not sound important when you checkout, but when you commit, git might not know enough to work alright.
回答这个问题 - 不,并且有一个有意义的理由。即使使用“稀疏结帐”,也会下载存储库的整个历史记录。澄清为什么这是必要的 - 否则跟踪重命名的文件将是......颈部的痛苦。想象一下,您将文件移动/repo_root/asd/file1.cpp
到/repo_root/fgh/file1.cpp
- 现在,如果您只下载了/repo_root/fgh
增量文件,您将不会知道 file1.cpp。所以这意味着您必须下载所有增量。但是你有一个完整的存储库;不仅仅是它的文件夹剪切,因此/rero_root/fgh
文件夹本身不是回购。当您结帐时,这听起来可能并不重要,但是当您提交时,git 可能不知道足以正常工作。
Workaround: If you really want to, you can create a script that calls git-checkout in such a manner (for the sh shell, batch for windows should not be hard to produce):
解决方法:如果你真的想要,你可以创建一个以这种方式调用 git-checkout 的脚本(对于 sh shell,windows 的批处理应该不难生成):
!/bin/sh
curDir=`pwd`
cd
git-checkout
cp -R /*
cd $curDir
Here the first argument is the branch to checkout, the second - the folder where the repo is currently present, the third - the subdir you want to really use, and the fourth - the location to which you want it copied.
这里的第一个参数是要结帐的分支,第二个参数是当前存储库所在的文件夹,第三个参数是您要真正使用的子目录,第四个参数是您希望将其复制到的位置。
Warning: my shell skills are almost non-existent, so use this after testing. It should not be hard to recreate the reverse of this script, that copies back stuff, so that it can be committed to the repo.
警告:我的shell技能几乎不存在,所以测试后使用这个。重新创建此脚本的反向操作应该不难,即复制回内容,以便将其提交到存储库。
回答by weynhamz
git filter-branch --subdirectory-filter
is what you need, see Detach (move) subdirectory into separate Git repository.
git filter-branch --subdirectory-filter
是您所需要的,请参阅Detach (move) subdirectory into separate Git repository。
Here is a little bash script to do that.
这是一个小 bash 脚本来做到这一点。
This will first make a working copy of the original repo, then filter branch using subdirectory filter to you get what you want.
这将首先制作原始存储库的工作副本,然后使用子目录过滤器过滤分支以获得您想要的。
#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks
cd
git filter-branch --subdirectory-filter --prune-empty --tag-name-filter cat HEAD -- --all
git reset --hard
git remote rm origin
refbak=$(git for-each-ref --format="%(refname)" refs/original/)
if [ -n "$refbak" ];then
echo -n $refbak | xargs -n 1 git update-ref -d
fi
git reflog expire --expire=now --all
git repack -ad
git gc --aggressive --prune=now
Use for the example in the question, git-subdir.sh repo perl
would work.
用于问题中的示例,git-subdir.sh repo perl
会起作用。
回答by Antoine Toulme
You can try braid - it tracks remotes while matching them to a path. https://github.com/evilchelu/braid/wiki
您可以尝试编织 - 它可以在将遥控器与路径匹配的同时跟踪遥控器。 https://github.com/evilchelu/braid/wiki
回答by Daemeon
It appears what you are trying to do is rename the directory tree such that your files end up in a different place. It appears to me that what you are asking to do is an anti-template for code/project management on two counts: categorization of modules (java bits under java node, perl under perl node), and having a project with files in different locations from where the developer visualizes them. Since git maintains hashes of directory contents to see what is changed, this also breaks git as such.
看来您要做的是重命名目录树,以便您的文件最终位于不同的位置。在我看来,您要求做的是在两个方面进行代码/项目管理的反模板:模块分类(java 节点下的 java 位,perl 节点下的 perl),以及在不同位置拥有一个包含文件的项目从开发人员将它们可视化的地方。由于 git 维护目录内容的哈希值以查看更改的内容,因此这也会破坏 git。
Daemeon Reiydelle
戴蒙·雷德尔