Git 1.7.0中的稀疏结帐?


70

借助Git 1.7.0中新的稀疏签出功能,是否有可能像在SVN中那样仅获取子目录的内容?我找到了这个示例,但是它保留了完整的目录结构。想象一下,我只想要“ perl”目录的内容,而没有一个名为“ perl”的实际目录。

-编辑-

例:

我的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

我想要的是能够从上述存储库中产生此布局:

repo/.git/
repo/script1.pl
repo/script2.pl

但是,使用当前的稀疏签出功能,似乎只能

repo/.git/
repo/perl/script1.pl
repo/perl/script2.pl

这不是我想要的。


4
他们终于实现了!凉!
Mauricio Scheffer'2

为什么?问题是什么?以及为什么要在存储库中具有不同的目录结构而在本地具有不同的目录结构?乍看之下没有多大意义。
吉里·克鲁达

2
@Jiri:我有一个带有ActionScript(客户端)和PHP(服务器端)代码的Web应用程序。这些文件密切相关,因此我想将它们放在单个回购/分支中。但是我不希望服务器上的动作脚本源文件只有PHP文件。
davr 2010年

2
@davr这不是罕见的情况,我想要确切的东西。可惜我还没明白。
preinheimer 2011年

@preinheimer,这也是我想要的东西。这将使开发和测试主题使我变得容易得多。
apokaliptis

Answers:


27

您仍然需要克隆整个存储库,其中将包含所有文件。您可以使用该--depth标志仅检索有限数量的历史记录。

克隆存储库后,读取树技巧将您对存储库的“视图”限制为仅这些文件或.git/info/sparse-checkout文件中的目录。

我编写了一个快速脚本来帮助管理稀疏性,因为目前它有点不友好:

#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
    echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD

如果将此脚本另存为git-sparse.sh通过调用报告的路径git --exec-path,则可以运行git sparse foo/ bar/以仅“签出” foo和bar目录,或者git sparse '*'重新获取所有内容。


感谢您的帮助,但这似乎无法回答我的问题。请参阅我更新的问题以进行澄清。
davr 2010年

3
是的,稀疏只是一种过滤实际树的方法,它无法移动文件。所以你不能做自己想做的...
richq 2010年

16

最简洁的答案是不。Git将所有文件视为一个单元。

我建议您将存储库分解为逻辑块。用于perl,图像和docs的单独文件。如果您还需要保持尤伯杯回购类,你可以创建一个回购协议由达子模块



5

现在无需深入说明为什么要这样做,您的问题可以(可能)通过符号链接/快捷方式轻松解决。

要回答这个问题-不,并且有有意义的理由。即使使用“稀疏签出”,也可以下载回购的全部历史记录。为了阐明为什么这样做是必要的-否则跟踪重命名的文件将是...的难题。假设您将文件移动/repo_root/asd/file1.cpp/repo_root/fgh/file1.cpp-现在,如果您仅下载了/repo_root/fgh增量文件,则将不了解file1.cpp。因此,这意味着您必须下载所有增量。但是,您有了一个完整的存储库;不仅是文件夹的一部分,因此/rero_root/fgh文件夹本身不是仓库。当您结帐时,这听起来可能并不重要,但是当您提交时,git可能并不了解足以正常工作的知识。

解决方法:如果确实需要,可以创建一个以这种方式调用git-checkout的脚本(对于sh shell,应该不难生成Windows批处理):

!/bin/sh
curDir=`pwd`
cd $2
git-checkout $1
cp -R $3/* $4
cd $curDir

在这里,第一个参数是要签出的分支,第二个参数是当前存储库所在的文件夹,第三个参数是您要真正使用的子目录,第四个参数是要将其复制到的位置。

警告:我的shell技能几乎不存在,因此请在测试后使用。重新创建此脚本的相反部分(复制回内容)并不难,这样就可以将其提交到存储库中。


拥有存储库的整个历史记录不是问题,这不是一个大的存储库,而且我们有足够的磁盘空间。我猜我们的特殊用例并不常见,因此git开发人员从未想过要添加它。这是SVN对我们更有效的少数事情之一(git在99件事上做的更好,这就是为什么我们切换了,但仍然如此)
davr 2011年

Windows上的符号链接是一场噩梦-这很难处理。
Alex Brown

3

git filter-branch --subdirectory-filter是您所需要的,请参阅将子目录分离(移动)到单独的Git存储库中

这是一个小bash脚本来执行此操作。

这将首先制作原始存储库的工作副本,然后使用子目录过滤器过滤分支以获取所需的内容。

#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks $1 $2

cd $2

git filter-branch --subdirectory-filter $2 --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

用于问题中的示例,git-subdir.sh repo perl将起作用。



0

您似乎正在尝试重命名目录树,以使文件最终位于其他位置。在我看来,您要执行的工作是针对代码/项目管理的一个反模板,有两个方面:模块分类(java节点下的java位,perl节点下的perl)以及在不同位置放置文件的项目从开发人员将其可视化的地方。由于git维护目录内容的哈希值以查看更改内容,因此这也破坏了git。

Daemeon Reiydelle

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.