基特 · 克隆: 只要文件,好吗?

我想克隆一个 GIT 回购和不结束与 .git目录。换句话说,我只想要那些文件。有办法吗?

git clone --no-checkout做了与我想要的完全相反的事情(只给了我 .git目录)。

我试图这样做的 遥控器回购,而不是一个本地的,这意味着这是 不是复制品的“ 如何进行“ git 导出”(如“ svn 导出”) ”(即使解决方案可能最终是相同的)。

135851 次浏览

为什么不执行一个克隆,然后删除 .git目录,这样您就只有一个空的工作副本?

编辑: 或者事实上为什么要用克隆呢?当你说你想要一个 git 回购但是没有 .git目录的时候,这有点令人困惑。如果您的意思是您只需要树的某个状态的副本,那么为什么不在 shell 中执行 cp -R而不是 git 克隆,然后删除 .git

你可以创建一个浅显的克隆,只得到最后几个版本:

 git clone --depth 1 git://url

然后简单地删除. git 目录或者使用 git archive导出树。

听起来你只是想要一份源代码的副本。如果是这样,为什么不直接复制目录并排除。Git 目录?

与您正在查找的内容最接近的 git 命令由 翻译: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对提供。
请参阅 使用 git 的备份项目: 它将在归档文件中包含所有文件(如果使用 git-archive-all脚本,则包括子模块)

然后您可以在任何地方使用该归档文件,只返回文件,不返回 .git目录。

git archive --remote=<repository URL> | tar -t

如果你只需要第一级的文件夹和文件:

git archive --remote=<repository URL> | tar -t --exclude="*/*"

仅列出远程回购的第一级文件夹:

git archive --remote=<repository URL> | tar -t --exclude="*/*" | grep "/"

注: 该 不适用于 GitHub (不支持)

所以你需要 克隆(浅层以加快克隆步骤) ,然后在本地存档:

git clone --depth=1 git@github.com:xxx/yyy.git
cd yyy
git archive --format=tar aTag -o aTag.tar

另一种选择是做一个浅克隆(如下所述) ,但是将. git 文件夹放在其他地方。

git --git-dir=/path/to/another/folder.git clone --depth=1 /url/to/repo

回购文件夹将只包含该文件,没有 .git

注意: git --git-dir命令 git的一个选项,而不是 git clone


Git 2.14.X/2.15更新(2017年第四季度) : 它将 确保避免添加空文件夹

git archive”,特别是在与 pathspec 一起使用时,存储一个空的 尽管 Git 本身从来不这样做,但是在其输出中。
这事已经解决了。

提交4318094(2017年9月12日) by René Scharfe (“)
建议者: 杰夫 · 金(peff)
(由 朱尼奥 · C · 哈马诺 gitster于2017年9月25日在 犯下罪行合并)

不要向归档添加空目录

虽然 git 不会跟踪空目录,但是 git archive可能会被骗将一些目录存入归档。
虽然对象数据库支持,但它不能在索引中表示,因此不太可能在野外发生。

由于 git 不支持空目录,因此它们也不应该被支持 写入档案。
如果确实需要一个空目录,那么可以通过在其中放置一个空的 .gitignore文件来跟踪和归档该目录。

git archive --format=tar --remote=<repository URL> HEAD | tar xf -

取自 给你

Git checkout-f

还有另一种方法可以做到这一点,那就是将回购从工作树中分离出来。

如果需要定期更新这些没有 git 的 git 文件,则此方法非常有用。例如,当我需要签出源代码文件并构建一个工件时,我使用它,然后将工件复制到不同的回购中,只是为了部署到服务器,当我想要源代码签出并构建到 www 目录时,我也使用它将源代码推送到服务器。

我们将创建两个文件夹,一个用于 git,一个用于工作文件:

mkdir workingfiles
mkdir barerepo.git

初始化一个赤裸裸的 git 回购:

cd barerepo.git
git --bare init

然后创建一个接收后挂钩:

touch hooks/post-receive
chmod ug+x hooks/post-receive

在你最喜欢的编辑器中编辑接收后的内容:

GIT_WORK_TREE=/path/to/workingfiles git checkout -f
# optional stuff:
cd down/to/some/directory
[do some stuff]

将其添加为远程控制:

git remote add myserver ssh://user@host:/path/to/barerepo.git

现在,每次你推到这个裸回购它将检查工作树到 /workingfiles/。但是 /workingfiles/本身不在版本控制之下; 在 /workingfiles/中运行 git status将产生错误 fatal: Not a git repository (or any parent up to mount point /data)。只是些普通文件。

与其他解决方案不同,rm -r .git命令是不需要的,所以如果 /workingfiles/是其他 git 回购,你不必担心命令使用删除其他回购的 git 文件。

git --work-tree=/tmp/files_without_dot_git clone --depth=1 \
https://git.yourgit.your.com/myawesomerepo.git \
/tmp/deleteme_contents_of_dot_git

/tmp 中的两个目录都是动态创建的,不需要预先创建。

根本不需要使用 git,只需在 URL (来源)中添加“/zipball/master/”即可。

下载中

这个解决方案最接近 github 页面上的“下载 ZIP”按钮。一个优势是缺乏。Git 目录。另一个-它下载单一的 ZIP 文件,而不是每个文件一个接一个,这可以作出巨大的差异。它可以通过 wget: wget -O "$(basename $REPO_URL)".zip "$REPO_URL"/zipball/master/从命令行完成。唯一的问题是,有些存储库可能根本没有主分支。如果是这种情况,URL 中的“ master”应该被适当的分支替换。

拉开拉链

一旦有了 ZIP,最终的解压缩目录名可能仍然是非常奇怪和意想不到的。为了解决这个问题,可以通过 这个剧本提取名称,并且 mv-ed 为 URL 的 basename。最终的 script.sh可能类似于(处理空格的评估) :

#Script for downloading from github. If no BRANCH_NAME is given, default is "master".
#usage: script.sh URL [BRANCH_NAME]
__repo_name__='basename "$1"'
__repo_name__="$(eval $__repo_name__)"
__branch__="${2:-master}"
#downloading
if [ ! -e ./"$__repo_name__"".zip" ] ; then
wget -O "$__repo_name__"".zip" "$1""/zipball/$__branch__/"
fi
#unpacking and renaming
if [ ! -e ./"$__repo_name__" ] ; then
unzip "$__repo_name__"".zip" &&
__dir_name__="$(unzip -qql $__repo_name__.zip | sed -r '1 {s/([ ]+[^ ]+){3}\s+//;q}')" &&
rm "$__repo_name__"".zip" &&
mv "$__dir_name__" "$__repo_name__"
fi

维持

这种方法应该可以解决“仅仅是文件”的问题,而且对于对小型存储库的快速一次性访问非常有用。

但是。如果源是相当大的,唯一的可能性更新是下载和重建所有,然后(据我所知)没有更新 .git-less 目录的可能性,所以完整的回购必须再次下载。那么最好的解决方案就是——正如 VonC 已经解释过的那样——坚持使用浅拷贝 git clone --depth 1 $REPO_URL。但接下来呢?要“检查更新”,请参阅 链接,要更新,请参阅伟大的维基样 回答

只要克隆它,然后删除. git 文件夹