做一个"git export"(比如"svn export")?

Greg Hewgill 2312 git export svn-export git-archive

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

  1. git clone然后删除.git存储库目录.
  2. git checkout-index 提到这个功能,但开头是"只需将所需的树读入索引...",我不完全确定如何做.
  3. git-export是第三方脚本,基本上git clone进入临时位置,然后rsync --exclude='.git'进入最终目的地.

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

CB Bailey.. 2354

实现这一目标的最简单方法可能就是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/

(有关详细信息,请参阅格雷格的答案)

  • 请注意,存档不包含.git目录,但会包含其他隐藏的git特定文件,如.gitignore,.gitattributes等.因此,如果您不想要它们,请确保使用export-ignore属性一个.gitattributes文件并在进行存档之前提交它.见http://feeding.cloud.geek.nz/2010/02/excluding-files-from-git-archive.html (220认同)
  • ZIP存档:`git archive --format zip --output/full/path master` (195认同)
  • 最简单的方法:`git archive -o latest.zip HEAD`它创建一个Zip存档,其中包含当前分支上最新提交的内容.请注意,输出格式是由输出文件的扩展名推断的. (88认同)
  • 要跟进Streams的注意事项:您可以在命令中添加'--prefix = something /'字符串来控制将在zip中打包的目录名称.例如,如果你使用`git archive --format zip --output /path/to/file.zip --prefix = newdir/master`,输出将被称为'file.zip',但当你打开它时,顶部级目录将是'newdir'.(如果省略--prefix属性,则顶级目录将为'file'.) (53认同)
  • 它不支持git子模块:( (37认同)
  • 很好,我在`〜/ .gitconfig`` [alias] zip = archive --format zip --output`中添加了zip选项作为别名.用法:`git zip~/Desktop/app.zip master` (6认同)
  • @Liam:是的,默认格式是`tar`,这就是为什么你可以*直接将输出管道输出到'tar -x`. (3认同)

Greg Hewgill.. 316

我发现了2选项意味着什么.从存储库中,您可以执行以下操作:

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

路径末尾的斜杠很重要,否则会导致文件位于/ destination中,前缀为"path".

由于在正常情况下索引包含存储库的内容,因此"将所需的树读入索引"没有什么特别之处.它已经存在了.

-a标志需要检出索引中的所有文件(我不确定在这种情况下省略此标志意味着什么,因为它不能做我想要的).该-f标志强制覆盖输出中的任何现有文件,此命令通常不会执行此操作.

这似乎是我正在寻找的那种"git export".

  • ...并且不要忘记结束时的滑动,否则你将无法达到预期的效果;) (73认同)
  • +1给conny的建议.另外,不要尝试创建'〜/ dest /',因为这会在您的工作目录中创建一个名为'〜'的目录,而不是您真正想要的目录.猜猜当你无意识地输入rm -rf~时会发生什么 (33认同)
  • @conny:阅读你的评论,忘了它并运行命令而没有斜杠.提示:按照conny的建议 - .- (7认同)
  • @KyleHeironimus - 如果您在前缀路径周围使用引号告诉shell不执行波浪扩展,那么关于使用'〜/ dest /`的警告是真的.在你的工作目录中将创建一个名为`~`(不是''〜'`!)的目录.关于`git checkout-index`在这方面没有什么特别之处:`mkdir'〜/ dest'`也是如此(*不要这样做!*).避免需要引用的文件名的另一个好理由(例如,其中有空格):-) (4认同)

小智.. 253

git archive 也适用于远程存储库.

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

要导出repo中的特定路径,请添加尽可能多的路径作为git的最后一个参数,例如:

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

  • 我试过:`git archive --format = zip --output foo.zip --remote = https://github.com/xxx.git master`并且致命:协议不支持操作.意外的命令流结束. (11认同)
  • **注意**:服务器必须启用此功能. (7认同)
  • @andyf GitHub上有自己的办法:`卷曲-L https://api.github.com/repos/VENDOR/PROJECT/tarball | 焦油xzf -`每[文档](https://developer.github.com/v3/repos/contents/#get-archive-link) (7认同)
  • 这是我最喜欢的选项.它还有一个额外的好处,它也适用于裸存储库. (6认同)
  • 改进的版本是:`git archive --format = tar --prefix = PROJECT_NAME/--remote = USER @ SERVER:PROJECT_NAME.git master | tar -xf -`(确保您的存档位于文件夹中) (5认同)

Anthony Hatz.. 57

在此输入图像描述

如果存储库托管在GitHub上,则应回答特殊情况.

只是用svn export.

As far as I know Github does not allow archive --remote. Although GitHub is svn compatible and they do have all git repos svn accessible so you could just use svn export like you normally would with a few adjustments to your GitHub url.

For example to export an entire repository, notice how trunk in the URL replaces master (or whatever the project's HEAD branch is set to):

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

And you can export a single file or even a certain path or folder:

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

Example with jQuery JavaScript Library

The HEAD branch or master branch will be available using trunk:

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

The non-HEAD branches will be accessible under /branches/:

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

All tags under /tags/ in the same fashion:

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


jperras.. 41

Git手册:

使用git-checkout-index"导出整个树"

前缀能力基本上使得git-checkout-index用作"export as tree"函数变得微不足道.只需将所需的树读入索引,然后执行:

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

  • 我认为混淆是"将所需的树读入索引"这一短语. (19认同)
  • 如果你想在分支栏中导出目录foo,那么这将是`git read-tree bar:foo`然后`git checkout-index --prefix = export_dir/-a`之后你可能应该做`git update-索引大师` (4认同)
  • 另外我会回复@ davetron5000,注释"将所需的树读入索引",我不知道这意味着什么. (3认同)

Daniel Schie.. 38

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

git export ~/the/destination/dir

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

安装简单; 只需将脚本放在您的某个位置PATH,并确保它是可执行的.

github存储库 git-export

  • 呃,这个脚本是57行文档,空白,设置,参数解析,只有一行实际上做了什么...... (16认同)
  • 这个包装器不是平台无关的; 它依赖于/ bin/sh.所以如果你在Windows上,这个解决方案_probably_将不适合你. (14认同)

kostmo.. 36

对于Git而言,这似乎不是SVN的问题.Git只在存储库根目录中放置一个.git文件夹,而SVN在每个子目录中放置一个.svn文件夹.所以"svn export"避免了递归命令行魔术,而Git递归则没有必要.

  • 从SVN 1.7开始,也只有一个.svn文件夹:https://subversion.apache.org/docs/release-notes/1.7.html#single-db (25认同)

aredridel.. 27

相当于

svn export . otherpath

在现有的回购中是

git archive branchname | (cd otherpath; tar x)

相当于

svn export url otherpath

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


小智.. 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
避免冗长

此外,您可以获取任何分支或标记,或者从SVN中的特定提交修订版添加SHA1(Git中的SHA1等同于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会不会删除任何文件,但将覆盖具有相同名称的文件没有任何警告

更新:为了避免斩首问题或在使用checkout导出标签,分支或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 -- ./

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

  • 这对我很有用.但起初我得到了"Not a git repository"错误消息.然后我发现"/ path/to/repo /"必须指向.git文件夹.所以这个工作: - git-dir =/path/to/repo/.git (3认同)

slatvick.. 21

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

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

  • --exclude-vcs如果你打算采取这种机智 (18认同)
  • 一个很好的解决方案,我会改变--exclude ='.*'到--exclude ='.git*' (8认同)
  • 作为一个FYI,我的`rsync`副本将参数列为`--cvs-exclude`.此外,它仍然复制`.gitattributes`和`.gitignore` (2认同)

Lars Schilli.. 19

在寻找导出git存储库的方法时,我经常点击此页面.我对这个问题的回答考虑了svn export与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.

  • **唯一的答案:***它来自深处.*`git archive | tar`方法不适用于POSIX不兼容的shell环境(例如,AppVeyor的基于CMD或PowerShell的CI),这是非理想的.`git checkout`方法修改主工作树的索引,这很糟糕.`git checkout-index`方法需要事先修改主工作树的索引,这甚至是非常糟糕的.传统的`git clone`方法在删除该历史记录之前克隆整个存储库的历史记录,这是浪费的.这是唯一理智的解决方案. (2认同)

Harmon.. 16

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

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

普通的老bash工作得很好:)

  • 有时你也想忽略`.gitignore`中的内容,这不会. (3认同)
  • 那些属于Web应用程序的文件及其名称以dot开头?:)想想.htaccess (2认同)

teleme.io.. 13

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

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

  • 老实说 - 这个答案,也是问题中的第一个答案 - 就是99%的时间你会做的事情.大多数这些答案都过于复杂. (3认同)

zeeawan.. 11

是的,是一个干净利落的命令,用于存档您的代码而不会在存档中包含任何git,并且可以传递而不必担心任何git提交历史记录.

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


dkinzer.. 10

我只想指出你的情况

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

然后你可以使用cp foo [destination]而不是提到的git-archive master foo | -x -C [destination].


bishop.. 10

对于GitHub用户,该git archive --remote方法不能直接使用,因为导出URL是短暂的.您必须向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


orkoden.. 9

您可以将任何提交的远程仓库归档为zip文件.

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


tocororo.. 8

Bash实现git-export.

我已经在自己的函数上对.empty文件创建和删除过程进行了细分,目的是在'git-archive'实现中重用它们(稍后将发布).

我还将'.gitattributes'文件添加到进程中,以便从目标导出文件夹中删除不需要的文件.在使'git-export'功能更有效的同时包含了流程的冗长.

"空" EMPTY_FILE =;

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'文件添加到空文件夹:...完成.

Check-Out Index组件:...已完成.

重置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 admin wheel 25445901 3月12日12:57 /tmp/rel-1.0.0.tgz

我现在已将'git archive'功能合并到一个使用'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;
  }


小智.. 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


skiphoppy.. 6

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

ETA(2012-09-06):哇,苛刻的downvotes.我仍然认为使用构建工具而不是源代码控制工具构建发行版会更好.我相信使用构建工具构建工件.在我目前的工作中,我们的主要产品是用蚂蚁目标建造的.我们正在切换源代码控制系统,并且这个蚂蚁目标的存在意味着迁移中的麻烦减少了.


小智.. 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


Ondra Žižka.. 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(是?)问题,但对于出口而言,上述问题无关紧要。


归档时间:

查看次数:

615824 次

最近记录:

1 年,8 月 前