我一直在想,是否有一个好的“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;
}
如果存储库托管在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
可能最简单的方法是使用git存档。如果你真的只需要扩展的树,你可以这样做。
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帮助存档,它非常灵活。
请注意,即使存档文件不包含.git目录,但它也会包含其他隐藏的特定于git的文件,如.gitignore、.gitattributes等。如果您不希望它们在存档文件中,请确保在.gitattr文件中使用export-ignore属性,并在进行存档之前提交该属性。阅读更多。。。
注意:如果您对导出索引感兴趣,命令是
git checkout-index -a -f --prefix=/destination/path/
(更多详情请参见Greg的回答)