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

git克隆,然后删除.git存储库目录。git签出索引暗示了这一功能,但以“只需将所需的树读入索引……”开头,我不完全确定该怎么做。gitexport是一个第三方脚本,本质上是将git克隆到临时位置,然后再将rsync--exclude='.git'复制到最终目标。

这些解决方案中没有一个让我感到满意。最接近svn导出的可能是选项1,因为两者都要求目标目录首先为空。但选项2似乎更好,假设我能够理解将树读入索引意味着什么。


当前回答

在添加前缀(例如目录名)时将git导出到zip存档:

git archive master --prefix=directoryWithinZip/  --format=zip -o out.zip

其他回答

我需要这个作为部署脚本,但我不能使用上面提到的任何方法。相反,我想出了一个不同的解决方案:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME="/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME

我认为@Aredridel的帖子是最接近的,但还有更多的内容——所以我将在这里补充这一点;问题是,在svn中,如果你在repo的子文件夹中,并且你做到了:

/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir

然后svn将导出所有受修订控制的文件(它们也可能是新添加的;或已修改的状态)-如果您在该目录中有其他“垃圾”(我不在这里计算.svn子文件夹,而是像.o文件这样的可见文件),它将不会导出;将仅导出SVN repo注册的那些文件。对我来说,一件好事是,这个导出还包括尚未提交的具有本地更改的文件;另一个好处是导出文件的时间戳与原始文件的时间相同。或者,正如svn help export所说:

从指定的工作副本导出干净的目录树路径1,修订版本REV(如果给出),否则在工作时路径2….如果未指定REV,则所有本地将保留更改。不受版本控制的文件将不能复制。

要了解git不会保留时间戳,请比较以下命令的输出(在您选择的git repo的子文件夹中):

/media/disk/git_svn/subdir$ ls -la .

…和:

/media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)

…无论如何,我注意到gitarchive会导致归档文件的所有时间戳都相同!git帮助存档说:

git存档在给定树ID时的行为与给定提交ID或标记ID时的不同。在第一种情况下当前时间用作存档中每个文件的修改时间。在后一种情况下,记录的提交时间在引用的提交对象中。

…但显然这两种情况都设置了“每个文件的修改时间”;从而不保留那些文件的实际时间戳!

因此,为了保留时间戳,这里有一个bash脚本,它实际上是一个“单行”,尽管有些复杂-所以下面以多行形式发布:

/media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\
  DEST="/media/diskC/tmp/subdirB"; \
  CWD="$PWD"; \
  while read line; do \
    DN=$(dirname "$line"); BN=$(basename "$line"); \
    SRD="$CWD"; TGD="$DEST"; \
    if [ "$DN" != "." ]; then \
      SRD="$SRD/$DN" ; TGD="$TGD/$DN" ; \
      if [ ! -d "$TGD" ] ; then \
        CMD="mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \
        echo "$CMD"; \
        eval "$CMD"; \
      fi; \
    fi; \
    CMD="cp -a \"$SRD/$BN\" \"$TGD/\""; \
    echo "$CMD"; \
    eval "$CMD"; \
    done \
)

请注意,假设您正在导出“当前”目录(上面的/media/disk/git_svn/subdr)中的内容,并且导出到的目标位置有些不方便,但它位于DEST环境变量中。请注意,使用此脚本;在运行上述脚本之前,必须自己手动创建DEST目录。

运行脚本后,您应该能够比较:

ls -la /media/disk/git_svn/subdir
ls -la /media/diskC/tmp/subdirB   # DEST

…并希望看到相同的时间戳(对于那些受版本控制的文件)。

希望这对某人有所帮助,干杯

如果存储库托管在GitHub上,则为特殊情况。

只需使用svn导出。

据我所知,Github不允许存档--远程。虽然GitHub是svn兼容的,而且他们确实有所有的git repos svn可访问,所以你可以像平常一样使用svn导出,只需对GitHub url进行一些调整。

例如,要导出整个存储库,请注意URL中的主干如何替换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分支或主分支将使用主干:

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

如果你想要一些与子模块一起工作的东西,这可能值得一试。

注:

MASTER_DIR=同时检出子模块的检出DEST_DIR=此导出的结束位置如果你有rsync,我想你可以用更少的球疼做同样的事情。

假设:

您需要从MASTER_DIR的父目录(即MASTER_DIRcd..)运行此命令DEST_DIR假定已创建。如果需要,这很容易修改为包含DEST_DIR的创建

cd MASTER_DIR&&tar-zcvf/DEST_DIR/export.tar.gz--exclude='.git*'.&&cd/DEST_DIR/&&tar xvfz导出.tar.gz&&rm导出.tar.gif

如果您也需要子模块,这应该可以做到:https://github.com/meitar/git-archive-all.sh/wiki