关于git:如何与Github Pages同步文档?

How can I sync documentation with Github Pages?

我和几个人一起做了一个项目,我们有一个README.md文件,其中包含一系列Github风格的降价,这些降价在我们的Github页面上呈现。我们还建立了一个Github页面分支,它位于Github组织的子域下,并在创建页面时使用自动页面生成器简单地加载到我们的README.md文件中。但是,我注意到,当我更新我们的README.md文件时,它不会更新项目页面。相反,我们必须转到github设置选项卡并重新创建项目页面,在执行此操作时重新加载README.md文件。

另外,在阅读了Github项目目录页上文档文件之间的相对链接工作之后。我非常喜欢降价,因为这样可以节省大量的时间,不用手工编写文档中的所有HTML。不过,我希望能够有一个README.md文件,该文件能够包含到位于docs/*.md的其他文档文件的相关链接。我希望有一个简单的解决方案,这样我的其他文档文件也可以包含在我的GH页面分支中,并托管在我的Github页面子域下,并被呈现和/或主题化。

换句话说,我的问题是:

  • 有没有办法让我的readme.md文件自动更新我的Github页面子域?
    • [编辑]:如果使用自动页面生成器,答案似乎是"否"。您必须转到repo的设置页面,并在每次发生更改时重新加载它,以便更新它。nbsp;
  • 有没有一种方法可以让我的相关链接指向我的readme.md文件上的文档在我的Github页面上工作,也许是我以某种方式将我的/docs/*.md同步到我的Github页面,并以某种方式呈现和/或主题化它们?
    • [编辑]:根据我在写这个问题后学到的知识,似乎只有通过使用静态站点生成器(如Ruby Gem Jekyll)以及下面的注释中提到的Github支持的Webhook的一些用法,Github页面上才可能出现这种情况。我正在尝试寻找一个最佳的解决方案。nbsp;
  • 更好的是,有没有一种更简单的方法可以做到这一点,也许我只有一份readme.md和文档的副本,可用于GH页面和我的主分支,并使所有事情变得简单?
    • [编辑]:看起来这一个几乎肯定是不可能的。我正在考虑在Github中内置某种东西的可能性。似乎对这类东西更好的支持将来可能会内置到Github页面中,或者至少我肯定希望如此。nbsp;


我将发布一个我设置的解决方案,它利用了这样一个事实:Github页面使用的是已经使用自动页面生成器的Jekyll。

  • git checkout gh-pages
  • 江户十一〔一〕号
  • 埃多克斯1〔2〕
  • 埃多克斯1〔3〕
  • 江户十一〔四〕号
  • index.md前面加上以下文字
  • nbsp;

    1
    2
    3
    ---
    layout: index
    ---

    您还需要打开index.html文件并进行以下更改:

  • README.md文件的标记中删除呈现的HTML。这通常在

    标记之间。将此HTML替换为文本{{ content }},这将允许我们将此文件用作jekyll。我们应用布局的文件将放置在内容标记所在的位置。

  • 找到项目页面主题的CSS。对我来说,这是一条像下面这样的线:

    江户十一〔11〕。

    需要将此更改为

    埃多克斯1〔12〕

  • 存储在站点上的任何其他将用于此布局的资产也需要以{{ site.path }}作为前缀。
  • 这样,Jekyll将把降价文件作为_layouts目录中index.html布局的内容呈现出来。为了使这个过程自动化,不仅仅是readme.md文件,还有您在主分支中可能拥有的其他文档,我采取了以下步骤:

    创建了名为post-commit的文件,其中包含以下内容:

    nbsp;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #!/bin/bash
    ###
    ### The following block runs after commit to"master" branch
    ###
    if [ `git rev-parse --abbrev-ref HEAD` =="master" ]; then

        # Layout prefix is prepended to each markdown file synced
        ###################################################################
        LAYOUT_PREFIX='---

    layout: index

    ---



    '

        # Switch to gh-pages branch to sync it with master
        ###################################################################
        git checkout gh-pages

        # Sync the README.md in master to index.md adding jekyll header
        ###################################################################
        git checkout master -- README.md
        echo -e $LAYOUT_PREFIX > index.md
        cat README.md >> index.md
        rm README.md
        git add index.md
        git commit -a -m"Sync README.md in master branch to index.md in gh-pages"

        # Sync the markdown files in the docs/* directory
        ###################################################################
        git checkout master -- docs
        FILES=docs/*
        for file in $FILES
        do
            echo -e $LAYOUT_PREFIX | cat -"$file"> temp && mv temp"$file"
        done

        git add docs
        git commit -a -m"Sync docs from master branch to docs gh-pages directory"

        # Uncomment the following push if you want to auto push to
        # the gh-pages branch whenever you commit to master locally.
        # This is a little extreme. Use with care!
        ###################################################################
        # git push origin gh-pages

        # Finally, switch back to the master branch and exit block
        git checkout master
    fi

    编辑:我为README.md文件和docs/*中的markdown更新了上述脚本,使它们都使用相同的布局文件。这是一个比我以前更好的设置。这个脚本放在您的.git/hooks/目录中。巴什一定在你的路上。

    用以下命令创建文件_config.yml

    1
    2
    markdown: redcarpet
    path: http://username.github.io/reponame

    上面的脚本还同步了master分支的docs/*目录中的标记文件,以便也可以在github页面站点上查看这些文件。如果您包含以下jquery函数以便从gh-pages分支上的锚中除去.md扩展,那么与这些文档的相对链接就可以工作。您可以将以下脚本添加到_layouts目录中的index.html中:

    1
    2
    3
    4
    5
    6
    7
    $(document).on('ready', function () {
        $('a').each(function (i, e) {
            var href = e.href;
            if (href.search('.md') > 0)
                $(this).attr('href', href.split('.md')[0]);
        });
    });

    编辑:我在我的存储库中更改了上面的代码,这是一种快速而肮脏的方法,但是如果你知道我的意思,它在任何情况下都不会正常工作。例如,标记文件company.mdata.md将无法正确处理。为了解决这个问题,我将这个脚本更新到下面的脚本中,该脚本将更仔细地签出href并删除扩展名(如果找到)。我还使脚本更通用,允许通过更改ext变量来删除其他扩展。代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $(function () {
        $('a').each(function () {
            var ext = '.md';
            var href = $(this).attr('href');
            var position = href.length - ext.length;
            if (href.substring(position) === ext)
                $(this).attr('href', href.substring(0, position));
        });
    });

    我在coryg89/docsync上设置了一个repo示例,它在这里有一个项目页面,如果您想了解所有这些如何一起工作的话。


    我对将自述文件与Github页面同步的问题的解决方案与上述略有不同。可以使用Github API返回呈现为HTML的降价文件,而不是使用单独的javascript降价引擎。

  • https://api.github.com/repos///contents/README.md中取出README.md
  • 解码base64响应:window.atob( JSON.parse( blob ).content );
  • 将解码后的README发送到json主体中的https://api.github.com/markdown

    1
    2
    3
    4
    5
     {
      "text":"<README>",
      "mode":"markdown",
      "context":"<owner>/<repo>"
     }
  • 像BradRhodes所做的那样,将呈现的HTML插入到DOM元素中。

  • 此方法的两个注意事项:

  • 执行两个串行请求会降低页面加载速度。
  • 访问GitHub API时可能会遇到速率限制。
  • 对于低流量页面,如果加载时间不是关键的(~1-2秒),那么上述方法就足够有效了。


    您可以使用documentup来呈现readme.md。


    另一个需要考虑的方法是设置一个预提交挂钩,它构建相关的页面。我在我的一个存储库中这样做。不过,您可能需要放弃自动页面生成器,只需自己推到gh-pages分支,并像Nathan建议的那样,做一些花哨的工作,将您的文档转换为HTML或Jekyll站点。

    在那个存储库中,我这样做是为了使gh-pagesmaster保持一致。还有很多其他方法可以做到这一点。但这可能不适合您的情况(您可能不希望它们相同)。

    不管怎样,我提出这个问题的理由是因为我希望有人有一个更好的工作流程。这个方法有点复杂,不灵活,它要求每个人保持他们的钩子同步。


    我对在您的文档站点和主Github repo之间共享单个自述文件有几个想法:

  • 您只能使用一个包含代码和Jekyll文档站点的GH页面分支。您的存储库可能会变得有点混乱,您需要在自述文件的顶部放置一个yaml头文件。它几乎支持相对链接。问题是,如果你想让Jekyll呈现你的标记,它会给它一个.html扩展名。也许有一种方法可以配置这个。我举了一个例子来看看它是否有效。

  • 您可以在文档站点中使用Ajax调用从主分支中读取自述文件,然后使用JavaScript标记渲染器进行渲染。如果不编写一些巧妙的javascript,这将需要更长的时间来加载,并且不支持相关链接。它也比IDEA 1更容易实现。


  • Nathan和BrandRhodes描述的另一种方法是使用一个伟大的工具:由RicoSta创建的flatDoc。克鲁兹。

    FlatDoc将由Ajax加载文档(readme.md或任何其他markdown文件),对其进行解析,并显示所有好东西,甚至还有用于导航的侧边栏菜单!

    它在其API中内置了一个助手方法,可以从Github repo master加载文件(但也可以从Web加载其他任何地方)。

    说明

    从将以下HTML模板复制到GH页面分支的index.html中开始。继续:

    • 将"用户"替换为您的Github用户名
    • 将"repo"替换为您的github repo名称
    • 将"您的项目"替换为项目名称

    在文件中。在浏览器中本地试用。然后提交并推动更改。现在,您的Github页面将始终使用主分支中的readme.md文件进行更新。

    如果默认主题对您不满意,您可以用自己的CSS重新设计它的样式。


    另一个我已经非常成功地工作的方法是使用Ajax来获取文档,使用GitHub API和一个JavaScript Markdown引擎来呈现HTML(正如Nathan建议的那样)。

  • 使用GitHub API和JSONP从GitHub获取文档
  • 从GitHub API解码响应中的base64内容
  • 使用javascript降价引擎呈现降价
  • 显示呈现的HTML
  • 内森表示了一些对性能的关注,但在我的经验中,它看起来很快就会加载,所以我不认为这实际上是一个问题。

    其优点是易于设置,即使您只是在GitHub上的浏览器中直接编辑标记,它也会始终更新您的文档。

    我在Github页面上的http://bradrodes.github.io/githubdocsync/设置了一个示例,以显示它的工作状态。


    我还想在master中编辑文档并在gh页面中发布文档-我喜欢使文档与源代码保持最新,这似乎是最好的方法。这是我正在进行的工作,但我以Cory的脚本为出发点,并对其进行了一些扩展,使其能够在开箱即用的情况下运行,只要有一个带有_layouts的gh pages分支(即jekyll站点)。它转换了反勾式围栏(用于代码块),这在Github源代码浏览中很好地工作,但在GH页面中却不工作。我使用了一个带有include的index.md来完成项目README.md,这样我可以添加一个头部和一些其他装饰。此版本还处理任何名为"docs"的嵌套目录中的文档,在具有多个模块(而不是git子模块,只是子目录)的项目中,这些目录非常有用:

    埃多克斯1〔32〕

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    #!/bin/bash
    ###
    ### The following block runs after commit to"master" branch
    ###
    if [ `git rev-parse --abbrev-ref HEAD` =="master" ]; then

        # function to convert a plain .md file to one that renders nicely in gh-pages
        function convert {
            # sed - convert links with *.md to *.html (assumed relative links in local pages)
            # awk - convert backtick fencing to highlights (script from bottom of file)
            sed -e 's/(\(.*\)\.md)/(\1.html)/g'"$1" | awk -f <(sed -e '0,/^#!.*awk/d' $0) > _temp && mv _temp"$1"
        }

        if ! git show-ref --verify --quiet refs/heads/gh-pages; then
            echo"No gh-pages, so not syncing"
            exit 0
        fi

        # Switch to gh-pages branch to sync it with master
        ###################################################################
        git checkout gh-pages

        mkdir -p _includes

        # Sync the README.md in master to index.md adding jekyll header
        ###################################################################
        git checkout master -- README.md
        if [ -f README.md ]; then
            cp README.md _includes/
            convert _includes/README.md
            git add README.md
            git add _includes/README.md
        fi

        # Generate index if there isn't one already
        ###################################################################
        if [ ! -f index.md ]; then
            echo -e '---
    title: Docs
    layout: default
    ---

    {% include README.md %}' > index.md
            git add index.md
        fi

        # Generate a header if there isn't one already
        ###################################################################
        if [ ! -f _includes/header.txt ]; then
            echo -e '---
    title: Docs
    layout: default
    home:
    ---

    ' > _includes/header.txt
            git add _includes/header.txt
        fi

        # Sync the markdown files in all docs/* directories
        ###################################################################
        for file in `git ls-tree -r --name-only master | grep 'docs/.*\.md'`
        do
            git checkout master --"$file"
            dir=`echo ${file%/*} | sed -e"s,[^/]*,..,g"`
            cat _includes/header.txt | sed -e"s,^home: .*$,home: ${dir}/,"> _temp
            cat"$file">> _temp && mv _temp"$file"
            convert"$file"
            git add"$file"
        done

        git commit -a -m"Sync docs from master branch to docs gh-pages directory"

        # Uncomment the following push if you want to auto push to
        # the gh-pages branch whenever you commit to master locally.
        # This is a little extreme. Use with care!
        ###################################################################
        # git push origin gh-pages

        # Finally, switch back to the master branch and exit block
        git checkout master
    fi

    exit $?

    #!/usr/bin/awk
    {
       # Replace backtick fencing (renders well when browsing github) with jekyll directives
       if (/```/) {
          IN = IN?0:1 # Are we already in a fenced section? Toggle.
          if (IN) { # If we are starting a fenced section
             if (/```\s*$/) {
               $0 = $0"text" # empty language is OK for backticks but not for jekyll
             }
             gsub(/```/,"{% highlight")
             print $0" %}"
          } else { # ending a fenced section
            print"{% endhighlight %}"
          }
        } else { # not a fencing line
          if (IN) { # but in a fenced section, so add indent to make sure code is rendered with [cc]
            print"   "$0
          } else {
            print
          }
        }
    }

    与原版的另一个不同之处在于,它在所有页面中都设置了一个变量page.home。这可以用来定位根目录的相对路径,因此可以用来定位静态资源,如css。在_layouts/.default.html中,我有:

    1
    <link rel="stylesheet" href="{{ page.home }}css/main.css">

    这样我就可以编辑CSS,在本地构建Jekyll站点,在浏览器中查看结果,而无需等待Github在服务器上构建它。


    这并不难,两份拷贝和粘贴到终端,你都设置好了。

    Jekyll允许您导入降价文件,然后它将负责将其转换为HTML。诀窍是将您的README.md导入到您的index.md文件中。我们可以这样做:

    值得一看的是如何在Github上建立一个超级准系统Jekyll站点(只有两个文件!)

    设置

    只需运行此一次性设置(将整个代码块和PASE复制到终端),就可以复制两个文件并使页面与当前的自述文件保持一致:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # Copy our two files to the gh-pages branch
    git checkout -b gh-pages &&
    wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/_config.yml &&
    wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/index.md &&
    #
    # Commit and publish our page on github
    git add -A && git commit -m"Create project github page" &&
    git push --set-upstream origin gh-pages |
    #
    git checkout master # go back to master branch

    号自动化

    然后,我们只需要在每次推送之前自动将所有更改从master复制到gh-pages分支。我们可以通过运行这个脚本来实现(您可以复制并粘贴到终端中)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $(cat > .git/hooks/pre-push << EOF
    #!/bin/sh
    we_are_in_gh_pages="\$(git branch | grep -G"* gh-pages")"

    if [ !"\$we_are_in_gh_pages" ];
      then
        git checkout gh-pages &&
        git rebase master &&
        git push -f &&
        git checkout master # go back to master branch
    fi
    EOF
    ) && chmod 775 .git/hooks/pre-push

    它将创建一个推送钩子,每次运行git push时,该钩子将所有更改从master分支复制到gh-pages

    就这样。完成。


    我最近制作了一个包GH页面生成器来解决这个问题——它使用多个MD文件和一个配置文件生成多页站点。

    它正确地更新了页面之间的所有链接。将更改提交回gh pages分支相对容易成为CI的一部分。

    我在这里和这里使用它。