使用子模块的git归档导出(git归档所有/递归)

20

我有一个使用Git进行版本控制的网站目录。像Twitter Bootstrap、colorbox和lessjs这样的必需库,我使用子模块来引用它们的代码版本而不是跟踪它们的源代码。

现在,我想部署该项目,因此我需要子模块的代码。但是,使用 git archive 命令不会获取子模块的源文件/代码。

以下三种方法试图实现我想要的效果,但都无法正常工作: 第一种方法

#!/bin/sh

export revision="$1"

export GIT_INDEX_FILE=".git/tmpindex"
rm -f "$GIT_INDEX_FILE"

git read-tree $revision

export up="$(pwd)"

read_one_level () {
        export GIT_ALTERNATE_OBJECT_DIRECTORIES="$GIT_ALTERNATE_OBJECT_DIRECTORIES":$(
            git submodule foreach 'echo "$up/$path/.git/objects"' |
            grep -E -v '^(Entering|No submodule mapping found)' |
            tr '\n' : |
            sed 's/:$//'
        )

        git submodule foreach '
                cd "$up"
                subcommit=$(git rev-parse :"$path")
                git rm --cached "$path"
                git read-tree -i --prefix="$path/" $subcommit
        ' >/dev/null
}

while git ls-files -s | grep -q ^160000; do
    read_one_level
done

git archive --format=tar $(git write-tree)

rm -f "$GIT_INDEX_FILE" 

Thomas Rast在http://git.661346.n2.nabble.com/Running-git-archive-recursively-over-submodules-td4577012.html中提到:

这在Windows和Linux上都会报错,指出没有找到对象文件。

第二种方法: https://github.com/meitar/git-archive-all.sh

在Windows上会提示找不到mktemp。而且从git-archive改为git archive后,在tar中并没有包含子模块的内容... :(

第三种方法: https://github.com/Kentzo/git-archive-all

我认为它已经过时了,因为不兼容最新的python 3.3,而且仍然无法在使用2.7时正常工作,因为samefile会报错。

所以我的问题是: 有没有最近的方法/方法来处理导出/归档包括子模块的git项目?

或者我应该检查子树是否适合此工作流程?

提前致谢


我是Kentzo/git-archive-all的作者。它现在支持Python 3.3了。还有其他问题吗? - Kentzo
7个回答

9
我正在使用以下代码。
git archive -o release.zip HEAD
git submodule --quiet foreach 'cd $toplevel; zip -ru release.zip $sm_path'

创建一个包含所有子模块的 git 仓库完整归档。

如果你想要更加高级一些,甚至可以通过以下方式重新编写 zip 注释:

echo -e "Repository:\n$(git rev-parse HEAD)\nSubmodule status:\n$(git submodule status)" | zip -u release.zip -z

使用infozip在Windows上进行全部操作。


$path已经被弃用,建议使用$sm_path代替(以避免与Windows中的PATH变量冲突)。 - Bram Schoenmakers
@BramSchoenmakers 谢谢,已修复。 - t-b
1
这不遵守子模块的 .gitignore。 - ptoinson
1
这也包括子模块目录中的.git文件。虽然还不错。 - WofWca

7

git-archive-all 可在 (https://pypi.org/project/git-archive-all/) 获取,使用 pip install git-archive-all 进行安装... 但请注意:仅支持 .tgz 格式的输出文件。 - Erich Kuester
抱歉,我刚刚检测到我的系统(Fedora 33)安装了1.17版本...最新版本对tar、tar.gz、tar.xz等没有问题。 - Erich Kuester

4
如果您像我一样支持KISS原则,您可以使用@t-b的答案,但我发现该解决方案无法实现嵌套子模块的存档。以下代码将有所帮助。
# archive main directory
$ git archive --format tar -o release.tar HEAD
# descend recursively and archive each submodule
$ git submodule --quiet foreach --recursive 'git archive --format tar --prefix=$displaypath/ -o submodule.tar HEAD'
# concatenate with main archive
$ TOPDIR=$(pwd) git submodule --quiet foreach --recursive 'cd $TOPDIR; tar --concatenate --file=release.tar $displaypath/submodule.tar; rm -fv $displaypath/submodule.tar'
$ gzip -9 release.tar

结果将会是文件 result.tar.gz,而不是 "HEAD",当然你也可以选择其他提交。

2

我们可以编写一个快速的bash脚本,将tar归档、模块和子模块合并后,再进行压缩。以下是一个包含2个子模块的示例:

#!/bin/bash

set -e

pwd=$(pwd)
date=$(date +%Y%m%d)
package=gitreponame
branch=master
name=tarbz2name
submodule1=/src/app/sub1/
submodule2=/src/sub2/

pushd ${package}
git checkout ${branch}
git pull
tag=$(git rev-list HEAD -n 1 | cut -c 1-7)
git archive --prefix="${name}/" --format=tar master > "$pwd"/${name}-${date}-${tag}.tar

git submodule update --init

cd ${submodule1}
git archive  --prefix="${name}${submodule1}" --format=tar master > "$pwd"/sb1.tar
cd -

cd ${submodule2}
git archive --prefix="${name}${submodule2}" --format=tar master > "$pwd"/sb2.tar
popd

tar -Af ${name}-${date}-${tag}.tar sb1.tar
tar -Af ${name}-${date}-${tag}.tar sb2.tar
bzip2 ${name}-${date}-${tag}.tar
rm sb1.tar sb2.tar

1

1
第二种方法:https://github.com/meitar/git-archive-all.sh 以独立的Bash脚本部署,并且似乎仍在维护中。我发现这是一个快速获取项目子模块快照的简单方法。它甚至可以捕获早期的修订版本(有点像,请参见下文):
git-archive-all.sh --tree-ish (tag) ## for example

以下是可能会导致问题的一些情况:

  • 当尝试使用--format选项时,我遇到了问题,但默认选项tar通常可以工作。

  • (非常)严重的问题是:它捕获了我的子模块,但仅捕获了当前版本,未捕获指定版本。糟糕!

作为Bash脚本,这可能需要某种Linux兼容性层(如Cygwin)才能在Windows下运行。


看起来这应该是Git的内置功能--用脚本拼凑太复杂了。我猜不多人使用子模块或者git-archive,所以想同时使用两者的人更少。


1
这种方法的显著优点是它甚至可以捕捉早期版本(尽管事实证明它并没有真正起作用)。我也不知道如何使用@Kentzo的解决方案自动完成这个过程。@Sergio的解决方案似乎(有点)可以做到这一点,但我还没有自己测试过。我猜你必须使用所有这些解决方案进行实际检出(和子模块更新)--这对于常规的git archive并非必需。 - Brent Bradburn

0
一个简单的解决方案是递归调用 git archive 来压缩子模块。
脚本应该放在 Git 仓库的根目录下(即.git文件所在的位置)。
脚本中硬编码了以下内容:
  • 脚本路径
  • 导出目录路径。
#!/bin/bash
###
# Script name: archive_git_repos_as_zips.sh
# Purpose: Recursively produce zip archives of nested Git repositories.
###

# Path to this script
export SCRIPT='/PATH/TO/SCRIPT/archive_git_repos_as_zips.sh'

# Target directory for storing zip files
ZIP_DIR='/PATH/TO/git_zip_exports'

PWD=`pwd`
THIS=`basename $PWD`

# Zip file path
ZIP_FILE="$ZIP_DIR/${THIS}.zip

echo -e "\nCreating: $ZIP_FILE"
git archive -o $ZIP_FILE HEAD
git submodule --quiet foreach '$SCRIPT'

# end #

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接