对于每个提交,在单独的存储库或分支中创建一个等效的已编译提交。

14

我正在使用Jekyll搭建网站,它可以将ERB、SASS等编译成普通的HTML和CSS。

大多数提交后,我希望编译网站并在另一个仓库或分支中提交已编译的版本,以便将其推送到静态服务器。

最好的方法是什么?

我已经有了解决方案,但我希望有更加优雅的解决方法。

5个回答

5
大多数提交后,我希望编译网站并将已编译的版本提交到单独的存储库或分支中,以便可以将其推送到静态服务器。
对于您来说,正确的关键字是“持续集成”。
您可以使用像Jenkins这样的CI软件在每次提交后,在创建或修改拉取请求后或仅夜间构建系统。
您在CI软件中配置的构建脚本负责部署构建工件,也就是您已编译的版本,到目标系统(例如s3 bucket)。您还可以对不同的git存储库进行程序化提交。
请查看此处:https://jenkins.io/doc/

谢谢你的回答。恐怕这可能对于这种情况来说有些过度,我希望能够找到一种简单的方法来使用Git完成它,所以我现在打算保持问题的开放状态。 - Zaz

2

根据您的要求:

我不建议您使用相同的存储库来存储已编译的代码。因为它可以从任何源代码状态获取,并且这将是信息的不必要副本。

所以,在这种情况下,您想要使用git作为CI工具。您应该为编译站点创建另一个存储库,并在每次需要时进行提交。

我建议您选择“生产”状态的分支。当您在该分支中提交时-代码应该被重新构建。让我们称其为“production”。

  1. 为生成的代码创建单独的git存储库。
  2. 将此代码放入您的src存储库的post-commit钩子中。 它将处理生产分支中的所有提交,将代码检出到临时目录,进行构建并提交更改。
srcDir='../srcWorkTree'
buildedRepo='../buildedRepo'

if [ `git rev-parse --abbrev-ref HEAD` == "production" ]; then
    echo "making builded code commit..."
    mkdir -p $srcDir
    # https://dev59.com/b2855IYBdhLWcg3wMRVW
    git checkout-index -a -f --prefix=$srcDir/

    bundle exec jekyll build --source $srcDir --destination $buildedRepo

    cd $buildedRepo
    git add -A
    commitInfo=$( git log -1 --pretty="%h %B" )
    git commit -m "autobuild for $commitInfo"
    # git push
fi

另一种变体

我猜想,你可以访问你的生产服务器。至少你提到了在那里有git仓库。因此,把代码构建到目标目录中的post-receive hook放在那里将更加清晰简单,而不是像我描述的那样在本地机器上进行。

我猜想这个仓库是“bare”的,因为你不应该在服务器上进行更改。

post-receive hook:

#!/bin/sh

siteDir='/var/www/site'
tmpSrcDir='/var/www/site'

echo "**** [builder's post-receive hook]"

while read oldrev newrev refname
do
    if [ $refname = refs/heads/production ]
    then
        GIT_WORK_TREE=$tmpSrcDir git checkout --detach $newrev

        bundle exec jekyll build --source $tmpSrcDir --destination $siteDir
    fi
done

exit 0

一些评论

我明白,你试图使用子模块来存储已构建的站点。我不建议这样做。因为你的源代码不依赖于构建的代码,所以这没有意义。


2
我建议另一种选择:不要将编译版本存储在git中,而是将它们存储在其他地方。
以下是我们的工作流程示例:
- 当我们需要测试特定提交时,我们通过CI流程运行它,生成.tar.gz归档文件,并使用部署工具在staging服务器上进行测试; - 当我们选择提交发布版本时,我们在git中对此提交进行标记,通过CI流程运行它,.tar.gz带有版本号并存储在部署服务器上的某个“releases/”目录中。
我们备份了“releases/”文件夹,但如果我们失去它,我们也可以根据标记从源代码重新构建任何特定版本。

2
你的解决方案会将“源提交”和“交付提交”(编译版本的 _site 文件夹)混合在同一个存储库中,这不是最佳实践(而且会使 Git 存储库的大小不必要地增加)。
我建议创建一个名为“site”的单独存储库,并将其作为子模块添加到当前存储库中,路径为 _site/。
cd /path/to/current/repo
git rm -R _site
git submodule add -- /url/repo/site _site

这样一来,每次您使用“bundle exec jekyll build”构建传递时,都会在一个单独的存储库(位于_site中)中完成,您可以直接添加、提交甚至推送到想要测试的位置。
然后,您回到主存储库,在那里添加和提交gitlink索引中的特殊条目),从而在源代码的确切版本与传递的确切版本(生成的站点)之间建立强大的链接。

啊,我忘了在我的解决方案中提到我使用了 git init _site/,所以提交实际上是发送到一个单独的仓库。我认为,如果有任何问题,源码 应该是子模块。 - Zaz
@Zaz 没错:仅使用 git init 不会使其成为子模块,而只是一个嵌套的 git 存储库,这是不好的,正如我在 http://stackoverflow.com/a/41968295/6309 中详细说明的那样。 - VonC
我在.gitignore中有_site/,这种设置会不会让我自己搬起石头砸自己的脚? - Zaz
@Zaz 是的:子模块要求您不要忽略嵌套存储库的根文件夹,因为它是一个gitlink(特殊条目引用嵌套存储库的SHA1)。 - VonC

1

_site/中初始化Git repo,然后添加一个Git post-commit hook:.git/hooks/post-commit

echo -n "Add commit to compiled version? (y/N) "
read answer < /dev/tty
if [ "$answer" != "y" ]; then exit; fi

message=$( git log -1 --pretty=%B )

git stash --all
bundle exec jekyll build

cd _site
    git add --all
    git commit -m "$message"
cd ..

git stash pop

现在,每次提交时,都会询问您是否要将提交添加到编译版本中。

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