是否进行“ git导出”(如“ svn导出”)?


2356

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

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

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


1
@rnrTom:请参阅Somov的答案。(tar存档中没有“压缩”的内容)。
etarion 2012年

23
@mrTom git archive --format zip --output "output.zip" master -0将为您提供未压缩的存档(-0是未压缩的标志)。git-scm.com/docs/git-archive

7
我同意@mrTom的观点,我认为归档文件是压缩还是未压缩不是主要问题。使用SVN,我可以export直接从远程存储库中获得一个250 kB的子目录(否则可能为200 MB,不包括修订版)-而且我只会在网络上进行250 kB(或大约)的下载传输。使用gitarchive必须在服务器上启用它(因此我无法尝试)- clone --depth 1从服务器可能仍会检索到25 MB的存储库,其中.git子文件夹仅占用15MB。因此,我仍然会说答案是“否”。
sdaau

@mrTom答案是肯定的。请参阅OP的答案-命令为git checkout-index
nocache

这是一个很好的简单方法:git archive -o latest.zip HEAD
Evgeni Sergeev

Answers:


2396

可能最简单的方法是使用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/

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


198
ZIP归档文件:git archive --format zip --output /full/path master
Vadim 2010年

221
请注意,归档文件将不包含.git目录,但将包含其他隐藏的特定于git的文件,例如.gitignore,.gitattributes等。因此,如果您不想使用它们,请确保在其中使用export-ignore属性.gitattributes文件,并在进行存档之前提交。见feeding.cloud.geek.nz/2010/02/...
mj1531

54
要跟踪Streams,请注意:您可以在命令中添加'--prefix = something /'字符串,以控制将打包在zip中的目录名称。例如,如果您使用git archive --format zip --output /path/to/file.zip --prefix=newdir/ master输出,则将其称为“ file.zip”,但将其解压缩时,顶级目录将为“ newdir”。(如果省略--prefix属性,则顶级目录为“文件”。)
艾伦·史密斯

89
最简单的方法:git archive -o latest.zip HEAD创建一个Zip存档,其中包含当前分支上最新提交的内容。请注意,输出格式是通过输出文件的扩展名推断出来的。
nacho4d 2011年

37
它不支持git子模块:(
umpirsky

320

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

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

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

因为在正常情况下索引包含存储库的内容,所以“将所需的树读入索引”不需要做任何特殊的事情。它已经在那里。

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

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


73
...并且不要忘记最后的成功,否则您将无法获得理想的效果;)
conny

1
git add命令会更改索引中的内容,因此,git status显示为“要提交” 的内容是HEAD与索引内容之间的差异
2009年

7
@conny:请阅读您的评论,将其忘记,并在命令后加上斜杠。提示:遵循conny的建议-.-
Znarkus 2010年

35
+1以康尼的建议。另外,不要尝试创建“〜/ dest /”,因为这会在您的工作目录中创建一个名为“〜”的目录,而不是您真正想要的目录。猜猜当您不注意键入rm -rf〜时会发生什么
Kyle Heironimus

5
@KyleHeironimus-关于使用'〜/ dest /`的警告是正确的,因为您在前缀路径周围使用引号会告诉外壳程序不要执行波浪号扩展。在您的工作目录中将创建一个名为~(not '~'!)的目录。git checkout-index在这方面没有什么特别的mkdir '~/dest':(不要这样做!)也是如此。避免文件名需要引用的另一个很好的理由(例如,其中包含空格):-)
Matt Wallis

254

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

6
这是我最喜欢的选项。它还有其他好处,它也可以在裸仓库上工作。
innaM,2009年

5
改进后的版本是:( git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf - 确保档案位于文件夹中)
Nick

7
注意:服务器必须启用此功能。
JakubNarębski2012年

12
我尝试过:git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git master并致命:操作不受协议支持。命令流意外结束。
andyf

7
@andyf GitHub有其自己的方式:curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -每个文档
主教

62

在此处输入图片说明

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

只需使用svn export

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

例如,要导出整个存储库,请注意trunkURL中的替换方式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分支或分支将可使用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

1
git archive只要您使用git协议,就https://可以git://在GitHub上正常工作,只需在URL中替换为。我不知道为什么GitHub不发布此隐藏功能。
尼尔·梅休

1
@NeilMayhew它对我不起作用,我明白了fatal: The remote end hung up unexpectedly。使用jQuery github repo在两个不同的服务器上尝试过。
Anthony Hatzopoulos '16

你是对的。我忘记了我曾经git config url.<base>.insteadOf用来缓存远程存储库。因此,我实际上使用的是file://URL。我怀疑它git archive是否可以与git://URL一起使用,因为它需要能够git-upload-archive在远程端运行。使用该ssh协议应该是可能的,除了github不允许它(Invalid command: 'git-upload-archive')。
Neil Mayhew

如果我想在内部托管的git存储库上使用类似github的本地服务器工具的任何方法?
克里斯,

1
赞成-Git没有此功能,这是完全奇怪的,我们不得不诉诸svn
Jason S

40

Git手册

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

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

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


19
我认为混淆是“将所需的树读入索引”这一短语。
davetron5000

4
如果要在分支栏中导出目录foo,则应为[foo]。git read-tree bar:foo然后git checkout-index --prefix=export_dir/ -a,也许应该这样做git update-index master
Pascal Rosin 2012年

1
@JohnWeldon是否需要您首先克隆存储库?如果是这样,那么我将不接受它,因为子目录的“ svn导出”的全部目的是直接获得该子目录的副本。如果某人有一个1GB的Git存储库,而我想要的只是一个10kB的子目录,那么要求我克隆整个东西是很疯狂的。
杰森·S

3
我也回声@ davetron5000,并带有“将所需的树读入索引”的注释,我不知道这是什么意思。
杰森·S

38

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

git export ~/the/destination/dir

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

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

的github存储库 git-export


15
该包装器与平台无关。它依赖于/ bin / sh。因此,如果您使用的是Windows,则此解决方案可能对您不起作用。
shovavnik

18
嗯,这个脚本是57行文档,空格,设置,参数解析,只有一行实际上在执行某些操作……
Vladimir Panteleev

36

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


26
从SVN 1.7开始,只有一个.svn文件夹:subversion.apache.org/docs/release-notes/1.7.html#single-db
kostmo 2011年

这不会摆脱svn export删除的任何其他构建文件。因此,这绝对不是答案。
ygoe 2014年

28

相当于

svn export . otherpath

现有回购中的是

git archive branchname | (cd otherpath; tar x)

相当于

svn export url otherpath

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

1
谢谢,这是我所缺少的...另外,要检查导出的时间戳(它们将不会像在文件中那样保留),请使用git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)...但是,使用时间戳进行归档并不是一件容易的事,因此我发布了下面的例子
sdaau 2014年

1
您可以将C选项用于tar而不是子外壳,如下所示: git archive branchname | tar xC otherpath
James Moore

提示Ctar 的选项仅是GNU Tar。
aredridel

22

如果您不使用排除文件,请.gitattributes export-ignore尝试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 -- ./

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


实际上,在众多建议和支持中,这对我来说最有效,没有任何压缩,对裸存储库(凹凸棒石)可以很好地工作。
Takehin

1
请注意,SHA1检出将在存储库中创建一个“斩首”问题
user5286776117878 2014年

实际上是@ITGabs,这不会下载“ .git”文件夹。因此,下载的文件夹不是git存储库,因此在技术上也不是“被斩首”
Fabio Marreco

@FabioMarreco斩首问题不在存储库中,不在导出/下载的文件中,我正在更新答案以获取更多详细信息
user5286776117878 2016年

3
这对我来说很棒。但是起初我收到“不是git存储库”错误消息。然后我发现“ / path / to / repo /”必须指向.git文件夹。这样就行了:--git-dir = / path / to / repo / .git
philburk

21

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

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

1
这样会不会错过名称以点开头的文件,例如.htaccess吗?
Greg Hewgill 2011年

8
一个好的解决方案,我将--exclude ='。*'更改为--exclude ='。git *'
schmunk 2011年

18
--exclude-VCS如果你打算借此圆通
辛勤工作

./FROM/可以作为远程仓库吗?
Resist Design

2
仅供参考,我的副本rsync将参数列为--cvs-exclude。此外,它仍然会复制.gitattributes.gitignore
Ryan Ransford 2014年

19

我在寻找导出git存储库的方法时经常访问此页面。我对这个问题的回答考虑了svn导出与git相比在设计上具有的三个属性,因为svn遵循集中式存储库方法:

  • 通过不导出所有修订版,将到远程存储库位置的流量最小化
  • 它在导出目录中不包含元信息
  • 使用svn导出特定分支是通过指定适当的路径来完成的

    git clone --depth 1 --branch master git://git.somewhere destination_path
    rm -rf destination_path/.git
    

构建特定版本时,克隆稳定分支(例如--branch stable或)很有用--branch release/0.9


如果目标存在并且非空,则此方法不起作用。
同名的

2
一个唯一的答案: 它来自深渊。git archive | tar方法不适用于POSIX不兼容的外壳环境(例如,AppVeyor的基于CMD或PowerShell的CI),这是不理想的。该git checkout方法修改了主要工作树的索引,这很糟糕。该git checkout-index方法要求事先修改主工作树的索引,这甚至更糟。传统git clone方法会在删除存储库历史记录之前克隆整个历史记录,这很浪费。这是剩下的唯一理智的解决方案。
塞西尔·库里

1
要在本地导出,请注意,要从中克隆的Git工作树的绝对路径应带有file://协议前缀(例如git clone --depth 1 --branch v3.14.15 file:///home/me/src_repo trg_repo)。否则,将发出"warning: --depth is ignored in local clones; use file:// instead."并执行标准而不是浅表的克隆,从而破坏了此答案的全部目的。敬礼!
塞西尔·库里

16

这将复制所有内容,减去.dot文件。我用它来将git克隆的项目导出到我的Web应用程序的git repo中,而没有.git内容。

cp -R ./path-to-git-repo / path / to / destination /

普通的旧bash效果很好:)


为什么不只是推送到远程?比bash更简单。
nurettin 2012年

2
属于Web应用程序的文件怎么办,其名称以点开头?:)考虑一下.htaccess
Artur

3
有时您还想忽略其中的内容.gitignore,而不会。
fregante 2015年

14

与克隆一样简单,然后删除.git文件夹:

git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git


4
老实说-这个答案在问题中也排名第一-是您将在99%的时间内要做的事情。这些答案大多数都过于复杂。
杰夫·尼克松

11

对于GitHub用户,该git archive --remote方法将无法直接使用,因为导出URL为ephemeral。您必须向GitHub询问URL,然后下载该URL。 curl使这变得容易:

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -

这将在本地目录中为您提供导出的代码。例:

$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf -
$ ls jpic-bashworks-34f4441/
break  conf  docs  hack  LICENSE  mlog  module  mpd  mtests  os  README.rst  remote  todo  vcs  vps  wepcrack

编辑
如果要将代码放入特定的现有目录(而不是来自github的随机目录):

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1

11

是的,是一个干净整洁的命令,用于在没有任何git包含在存档中的情况下存档您的代码,并且很好地传递而无需担心任何git提交历史记录。

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

这很棒,只需要删除gitignore之后就可以完成共享了。
索格尔

使用.gitattributes文件,请参阅:删除.gitgnore等是公认的答案评论提到feeding.cloud.geek.nz/posts/excluding-files-from-git-archive
Sogger

10

我只想指出,在这种情况下

  1. 导出存储库的子文件夹(这就是我以前使用SVN导出功能的方式)
  2. 可以将所有内容从该文件​​夹复制到部署目标
  3. 并且由于您已经拥有整个存储库的副本。

然后,您可以使用cp foo [destination]来代替git-archive master foo | -x -C [destination]


9

您可以在任何提交时将远程仓库归档为zip文件。

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT

8

Bash实现git-export。

我已经将.empty文件创建和删除过程按其功能进行了细分,目的是在“ git-archive”实现中重用它们(将在稍后发布)。

我还将“ .gitattributes”文件添加到了该过程中,以便从目标导出文件夹中删除不需要的文件。在使“ git-export”功能更有效的同时,使流程更加详细。

EMPTY_FILE =“。empty”;

function create_empty () {
## Processing path (target-dir):
    TRG_PATH="${1}";
## Component(s):
    EXCLUDE_DIR=".git";
echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
    find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
#echo "done.";
## Purging SRC/TRG_DIRs variable(s):
    unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
    return 0;
  }

declare -a GIT_EXCLUDE;
function load_exclude () {
    SRC_PATH="${1}";
    ITEMS=0; while read LINE; do
#      echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
      GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
    done < ${SRC_PATH}/.gitattributes;
    GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}";
## Purging variable(s):
    unset SRC_PATH ITEMS;
    return 0;
  }

function purge_empty () {
## Processing path (Source/Target-dir):
    SRC_PATH="${1}";
    TRG_PATH="${2}";
echo -e "\nPurging Git-Specific component(s): ... ";
    find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
    for xRULE in ${GIT_EXCLUDE[@]}; do
echo -en "    '${TRG_PATH}/{${xRULE}}' files ... ";
      find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
echo "done.'";
    done;
echo -e "done.\n"
## Purging SRC/TRG_PATHs variable(s):
    unset SRC_PATH; unset TRG_PATH;
    return 0;
  }

function git-export () {
    TRG_DIR="${1}"; SRC_DIR="${2}";
    if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi
    load_exclude "${SRC_DIR}";
## Dynamically added '.empty' files to the Git-Structure:
    create_empty "${SRC_DIR}";
    GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
    git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
    if [ "${?}" -eq 0 ]; then echo " done."; fi
    /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
echo -en "\nChecking-Out Index component(s): ... ";
    git checkout-index --prefix=${TRG_DIR}/ -q -f -a
## Reset: --mixed = reset HEAD and index:
    if [ "${?}" -eq 0 ]; then
echo "done."; echo -en "Resetting HEAD and Index: ... ";
        git reset --soft HEAD^;
        if [ "${?}" -eq 0 ]; then
echo "done.";
## Purging Git-specific components and '.empty' files from Target-Dir:
            purge_empty "${SRC_DIR}" "${TRG_DIR}"
          else echo "failed.";
        fi
## Archiving exported-content:
echo -en "Archiving Checked-Out component(s): ... ";
        if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
        cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
echo "done.";
## Listing *.tgz file attributes:
## Warning: Un-TAR this file to a specific directory:
        ls -al ${TRG_DIR}.tgz
      else echo "failed.";
    fi
## Purgin all references to Un-Staged File(s):
   git reset HEAD;
## Purging SRC/TRG_DIRs variable(s):
    unset SRC_DIR; unset TRG_DIR;
    echo "";
    return 0;
  }

输出:

$ git-export /tmp/rel-1.0.0

将“ .empty”文件添加到空文件夹:...已完成。

签出索引组件:...已完成。

重置HEAD和索引:...完成。

清除特定于Git的组件:...

'/tmp/rel-1.0.0/{.buildpath}'文件...完成。

'/tmp/rel-1.0.0/{.project}'文件...完成。

'/tmp/rel-1.0.0/{.gitignore}'文件...完成。

'/tmp/rel-1.0.0/{.git}'文件...完成。

'/tmp/rel-1.0.0/{.gitattributes}'文件...完成。

'/tmp/rel-1.0.0/{*.mno}'文件...完成。

'/tmp/rel-1.0.0/{*~}'文件...完成。

'/tmp/rel-1.0.0/{.*~}'文件...完成。

'/tmp/rel-1.0.0/{*.swp}'文件...完成。

'/tmp/rel-1.0.0/{*.swo}'文件...完成。

'/tmp/rel-1.0.0/{.DS_Store}'文件...完成。

'/tmp/rel-1.0.0/{.settings}'文件...完成。

'/tmp/rel-1.0.0/{.empty}'文件...完成。

完成。

归档检出的组件:...已完成。

-rw-r--r-- 1个管理轮25445901 11月3日12:57 /tmp/rel-1.0.0.tgz

现在,我已经将“ git归档”功能合并到一个使用“ create_empty”功能和其他功能的单一过程中。

function git-archive () {
    PREFIX="${1}"; ## sudo mkdir -p ${PREFIX}
    REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
    RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
    USER_PATH="${PWD}";
echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
## Dynamically added '.empty' files to the Git-Structure:
    cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
#    git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
# e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
    OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz";
    git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
    cd "${USER_PATH}";
    if [[ "${3}" =~ [--explode] ]]; then
      if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
      mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
    fi
## Purging SRC/TRG_DIRs variable(s):
    unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
    return 0;
  }

用法:git-archive [/ var / www / htdocs] /repos/web.domain/website:rel-1.0.0
tocororo 2011年

8

如果您想要与子模块一起使用的东西,那么值得一试。

注意:

  • MASTER_DIR =签出您的子模块也签出
  • DEST_DIR =此导出将在哪里结束
  • 如果您有rsync,我认为您可以以更少的球痛做同样的事情。

假设:

  • 您需要从MASTER_DIR的父目录(即从MASTER_DIR cd ..)运行此文件
  • 假定已创建DEST_DIR。如果您愿意,可以很容易地对其进行修改以包括DEST_DIR的创建

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


6

我的偏好实际上是在Makefile(或其他构建系统)中有一个dist目标,该目标可以导出代码的可分发存档(.tar.bz2,.zip,.jar或任何适当的文件)。如果您碰巧正在使用GNU自动工具或Perl的MakeMaker系统,那么我认为这自动存在。如果没有,我强烈建议添加它。

预计到达时间(2012-09-06):哇,严厉的反对票。我仍然认为,使用构建工具而不是源代码控制工具来构建发行版会更好。我相信使用构建工具来构建工件。在我目前的工作中,我们的主要产品是使用蚂蚁目标制造的。我们正处在切换源代码控制系统的过程中,而这个ant目标的存在意味着迁移的麻烦减少了。


我想到的项目不是代码项目。它恰好是一个网站项目。
格雷格(Greg Hewgill)

没有解决这个问题。
Andrew Ferrier 2012年

1
是的,这样的答案可能并不适合每个人的需求,但是反对票是奇怪的。这一个完全有效的答案,实际上,在许多情况下,这是唯一正确的答案。很有道理的是,将这个问题视为“ vc工具问题”通常会完全走错了路。
snogglethorpe

6

这会将一系列提交(C到G)中的文件复制到tar文件中。注意:这只会获取已提交的文件。不是整个存储库。从这里稍微修改

提交历史记录示例

A-> B-> C-> D-> E-> F-> G- > H-> I

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar

git-diff-tree手册页

-r->递归到子树

--no-commit-id-> git diff-tree在适用时输出带有提交ID的行。该标志禁止提交ID输出。

--name-only->仅显示已更改文件的名称。

--diff-filter = ACMRT->仅选择这些文件。请参阅此处以获取文件的完整列表

C..G->提交范围内的文件

C〜->包括Commit C中的文件。不仅仅是Commit C之后的文件。

| xargs tar -rf myTarFile->输出到tar


5

就我所知,这个问题更多的是从服务器上下载某些状态,而没有历史记录,也没有其他分支的数据,而不是从本地存储库中提取状态(就像这里的许多助手一样)。

可以这样完成:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch 自Git 1.7.10(2012年4月)起可用。
  • --depth(是?)问题,但是对于出口而言,上述问题应该无关紧要。

注意:我只是注意到有2页的答案,在发布之前我只看了一页。有一个类似的anwser仅具有--depth,表示--single-branch除非--no-single-branch给出,否则意味着可能具有相同的效果。但是不确定,有些专家可以确认吗?
OndraŽižka18年

4

我需要一个部署脚本,但无法使用任何上述方法。相反,我想出了一个不同的解决方案:

#!/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

读取树/签出索引或存档解决方案有什么问题?据我所知,您已经完成了类似的操作,mkdir -p "$2" && git --git-dir="$1" archive HEAD | tar -x -C "$2"但操作时间更长。
CB Bailey

1
我无法从远程存储库获取读取树,并且归档解决方案不适用于github。
troelskn

是的,使用存档时收到无效命令:'git-upload-archive'...错误,并且我没有core.gitProxy配置选项和GIT_PROXY_COMMAND环境变量设置
tgkprog 2014年

4

这样做很简单,这是.bash_profile的功能,它直接将存档解压缩到当前位置,首先配置您通常的[url:path]。注意:使用此功能可以避免克隆操作,它直接从远程存储库获取。

gitss() {
    URL=[url:path]

    TMPFILE="`/bin/tempfile`"
    if [ "$1" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "$2" = "" ]; then
        TREEISH="HEAD"
    else
        TREEISH="$2"
    fi
    echo "Getting $1/$TREEISH..."
    git archive --format=zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
    rm $TMPFILE
}

.gitconfig的别名,需要相同的配置(请在.git项目中执行命令TAKE CARE,它总是像此处所说的那样一直跳至基本目录,直到此问题修复为止,我个人更喜欢该功能

ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -


4

如果您要在其中创建导出的计算机上有存储库的本地副本,那么我还有另一种解决方案可以很好地工作。在这种情况下,请移至该存储库目录,然后输入以下命令:

GIT_WORK_TREE=outputdirectory git checkout -f

如果您使用git存储库管理网站,并想在中签出干净版本,则此功能特别有用/var/www/。在这种情况下,请将此命令添加到.git/hooks/post-receive脚本中(hooks/post-receive在裸存储库中,这种情况下更适合)


3

我认为@Aredridel的帖子最近,但是还有更多内容-所以我将在此处添加;问题是在中svn,如果您位于存储库的子文件夹中,则可以执行以下操作:

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

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

  1. 将PATH1指定的工作副本(如果已提供,版本为REV,否则为WORKING)中的干净副本目录树导出到PATH2。...如果未指定REV,则将保留所有本地更改。不受版本控制的文件将不会被复制。

要意识到这git不会保留时间戳,请比较以下命令的输出(在git您选择的存储库的子文件夹中):

/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 -)

...而且无论如何,我都注意到git archive导致存档文件的所有时间戳都相同!git help archive说:

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

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

因此,为了保留时间戳,下面是一个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/subdir)中的内容,并且要导出到的目标位置有些不便,但是它在DEST环境变量中。请注意,使用此脚本;您必须先DEST手动创建目录,然后再运行上述脚本。

脚本运行后,您应该可以进行比较:

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

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

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


3

在添加前缀(例如目录名称)的同时,将git导出到zip归档文件:

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


1

我的.bashrc文件中具有以下实用程序功能:它在git存储库中创建当前分支的存档。

function garchive()
{
  if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
EOF
  else
    local oname=$1
    set -x
    local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
    git archive --format zip --output ${oname} ${bname}
    set +x
  fi
}
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.