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

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

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


当前回答

Bash实现git导出。

我已经将.empty文件的创建和删除过程划分为各自的功能,目的是在“gitarchive”实现中重新使用它们(稍后将发布)。

我还将“.gitattributes”文件添加到进程中,以便从目标导出文件夹中删除不需要的文件。在使“gitexport”功能更高效的同时,还包含了对流程的详细描述。

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导出/tmp/rel-1.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/{*~}”文件。。。完成。”“/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 3 11月12:57/tmp/rel-1.0.tgz我现在已经将“gitarchive”功能合并到一个使用“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_WORK_TREE=输出目录数字检出-f

如果您使用git存储库管理网站,并且希望在/var/www/中签出一个干净的版本,这一点特别有用。在这种情况下,将此命令添加到.git/hook/post-rereceive脚本中(在裸存储库上使用hook/post-Rereceive,这更适合这种情况)

您可以在任何提交时将远程回购存档为zip文件。

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

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

ETA(2012-09-06):哇,一票否决。我仍然认为,使用构建工具而不是源代码控制工具来构建发行版更好。我相信使用构建工具构建工件。在我目前的工作中,我们的主要产品是以蚂蚁为目标构建的。我们正处于切换源代码控制系统的过程中,这个蚂蚁目标的出现意味着迁移过程中少了一点麻烦。

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

注:

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

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

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

路径结尾处的斜线很重要,否则将导致文件位于带有前缀“path”的/target中。

因为在正常情况下,索引包含存储库的内容,所以“将所需的树读入索引”没有什么特别的事情可做。它已经在那里了。

签出索引中的所有文件都需要-a标志(我不确定在这种情况下省略此标志意味着什么,因为它不能满足我的需要)。-f标志强制覆盖输出中的任何现有文件,而此命令通常不会这样做。

这似乎是我想要的那种“git导出”。