是否执行 “git export”(例如 “svn export”)?

我一直在想是否有一个好的 “git export” 解决方案来创建没有.git存储库目录的树的副本。我至少知道三种方法:

  1. git clone然后删除.git存储库目录。
  2. git checkout-index暗示了此功能,但以 “仅将所需的树读入索引...” 开头,我不确定该怎么做。
  3. git-export是第三方脚本,其本质上是将git clone到一个临时位置,然后将rsync --exclude='.git' git clone到最终目标位置。

这些解决方案都没有使我感到满意。最接近svn export选项可能是选项 1,因为这两个选项均要求目标目录首先为空。但是,假设我能弄清楚将树读入索引的含义,选项 2 似乎更好。

答案

可能最简单的方法是使用git archive 。如果您真的只需要扩展树,则可以执行以下操作。

git archive master | tar -x -C /somewhere/else

在大多数情况下,我需要从 git 中 “导出” 某些内容,无论如何我都想要压缩的存档,所以我要做类似的事情。

git archive master | bzip2 >source-tree.tar.bz2

ZIP 存档:

git archive --format zip --output /full/path/to/zipfile.zip master

git help archive以获取更多详细信息,它非常灵活。


请注意,即使存档中不包含. git 目录,但是该存档中也会包含其他隐藏的特定于 git 的文件,例如. gitignore,.gitattributes 等。如果您不希望它们出现在存档中,请确保请在. gitattributes 文件中使用 export-ignore 属性,并在进行归档之前提交。 阅读更多...


注意:如果您有兴趣导出索引,则命令为

git checkout-index -a -f --prefix=/destination/path/

(有关更多详细信息,请参见格雷格的答案

我发现了选项 2 的含义。在存储库中,您可以执行以下操作:

git checkout-index -a -f --prefix=/destination/path/

路径末尾的斜杠很重要,否则它将导致文件位于 / destination 中,且前缀为 “path”。

由于在正常情况下索引包含存储库的内容,因此无需执行任何特殊操作即可 “将所需的树读入索引”。它已经在那里。

需要使用-a标志来检出索引中的所有文件(我不确定在这种情况下忽略此标志的含义,因为它不执行我想要的操作)。 -f标志强制覆盖输出中的所有现有文件,此命令通常不会执行此操作。

这似乎是我一直在寻找的 “git export”。

git archive也可以与远程存储库一起使用。

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -

要在仓库中导出特定路径,请在 git 的最后一个参数中添加任意数量的路径,例如:

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv

在此处输入图片说明

如果存储库托管在 GitHub 上,则是一个特殊情况的答案。

只需使用svn export

据我所知 Github 不允许archive --remote 。尽管 GitHub 与svn 兼容,并且它们确实可以访问所有 git repos svn所以您可以像平常一样使用svn export ,对 GitHub url 进行一些调整。

例如,要导出整个存储库,请注意 URL 中的trunk如何替换master (或项目的 HEAD 分支设置为 ):

svn export https://github.com/username/repo-name/trunk/

您可以导出一个文件,甚至可以导出某个路径或文件夹:

svn export https://github.com/username/repo-name/trunk/src/lib/folder

jQuery JavaScript 库示例

HEAD分支或master分支将使用trunk可用:

svn ls https://github.com/jquery/jquery/trunk

HEAD 分支可以在/branches/下访问:

svn ls https://github.com/jquery/jquery/branches/2.1-stable

/tags/下的所有标签都采用相同的方式:

svn ls https://github.com/jquery/jquery/tags/2.1.3

Git 手册

使用 git-checkout-index 来 “导出整个树”

前缀功能基本上使将 git-checkout-index 用作 “导出为树” 功能变得微不足道。只需将所需的树读入索引,然后执行:

$ git checkout-index --prefix=git-export-dir/ -a

我围绕git-checkout-index编写了一个简单的包装,您可以像这样使用:

git export ~/the/destination/dir

如果目标目录已经存在,则需要添加-f--force

安装简单;只需将脚本放在PATH某个位置,并确保其可执行。

git-export的 github 存储库

看来,与 SVN 相比,这不是 Git 的问题。 Git 仅在存储库根目录中放置一个. git 文件夹,而 SVN 在每个子目录中放置一个. svn 文件夹。因此,“svn 导出” 避免了递归命令行魔术,而使用 Git 则不需要递归。

相当于

svn export . otherpath

现有回购中的是

git archive branchname | (cd otherpath; tar x)

相当于

svn export url otherpath

git archive --remote=url branchname | (cd otherpath; tar x)

如果您不使用.gitattributes export-ignore排除文件, .gitattributes尝试git checkout

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q

-F
从索引中检查路径时,不要在未合并的条目上失败;相反,未合并的条目将被忽略。

-q
避免冗长

另外,您只需添加 SHA1(Git 中的 SHA1 等同于 SVN 中的修订号)就可以从 SVN 中获得任何分支或标签或从特定的提交修订中获得

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./

/path/to/checkout/必须为空,Git 不会删除任何文件,但是会覆盖相同名称的文件而不会发出任何警告

更新:为避免斩首问题或在使用带标签,分支或 SHA1 的结帐进行导出时保持完整的工作存储库,您需要在末尾添加-- ./

双破折号--告诉 git 破折号后的所有内容都是路径或文件,并且在这种情况下还告诉git checkout不更改HEAD

例子:

该命令将仅获取 libs 目录以及该确切提交的readme.txt文件

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt

这将创建(覆盖) my_file_2_behind_HEAD.txt在头HEAD^2之后两次提交

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt

获取另一个分支的出口

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./

请注意,。 ./相对于存储库的根目录

我广泛使用 git-submodules。这对我有用:

rsync -a ./FROM/ ./TO --exclude='.*'