Git Rebase 黄金法则问题

Git Rebase 黄金法则问题

git 整合来自不同分支的修改主要有两种方法:merge 操作和rebase操作,
merge初学者可能很熟悉。我们今天来主要说一下 rebase 操作,文章结尾会简单说一下 merge 操作的 –no-ff 参数问题。

rebase的简单定义:你可以把某一分支的所有修改都移至另外一个分支就像重新播放一样。
有点儿像金庸武侠小说里面的乾坤大挪移。
举个🌰
假设我们本地库的代码,如下所示

1
2
3
      A---B---C  remotes/origin/master
/
D---E---F---G master

如果此时我们执行 git pull 操作,就会变成下面的样子,因为 pull 默认执行的是 merge 操作,多出来H这次没必要的提交。如下所示

1
2
3
     A---B---C  remotes/origin/master
/ \
D---E---F---G---H master

如果我们执行 git pull –rebase 操作,将会变成下面的样子,这里我们用rebase代替了默认的merge操作

1
2
3
4
5
            remotes/origin
|
D---E---A---B---C---F---G
|
master

rebase 作用就是变成线性了,这在多人协作的情况变得非常关键。因为多人合作是不允许随意制造分叉的。大家可以参考我这篇文章。

这就引出了这篇博文要主要阐述的问题,rebase golden rule 问题。

Rebase golden rule
“No one shall rebase a shared branch” — Everyone about rebase

简单来说就是不要在你的公共分支上做任何rebase操作。
再举一个🌰。

图一是我们做rebase操作前的样子

image.png

图二是我们正确rebase的结果,即在feature分支执行rebase develop命令

image.png

图三是我们错误rebase的结果,即违反黄金法则的结果,我们在develop分支上执行了rebase feature操作

image.png

当我们在图三这种情况下对develop分支进行提交的话,会发现和远程分支冲突,然后我们手动或自动解决冲突,继续提交上去之后发现,我们修改的功能代码已经提交上去了,但是当我们看我们提交历史的记录的时候会发现有一部分重复的提交log。
这就是问题所在,你的项目组长是绝对不允许在他的项目里出现这种情况,因为会影响后续的代码追查,code review等问题。
说完了这个问题,这篇博文的主要任务基本完成了,最后在简单说一下 merge 的 –no-ff 参数,这也是我们在分支合并的时候经常遇到的问题。
–no-ff 的意思就是关闭 merge 的 fast-forwarded,merge 操作默认执行的是 fast-forwarded。
fast-forwarded 的意思就是在合并分支的时候,如果不涉及三方合并,git 只会简单的移动指针。
再再举一个🌰

1
2
3
4
5
6
7
        dev
|
A---B---C
\
D---E
|
feature

此时我们执行 merge –no-ff 操作,将会得到如下图

1
2
3
4
5
                dev
|
A---B---C--------F
\ /
D---E

执行 merge 之后得到的结果如下

1
2
3
               dev
|
A---B---C---D---E

如上git 将指针从C移到了E。

简单来说就是 –no-ff 的作用就是保持分支的非线性。方便我们看到分支的变化。

本文作者: Frank
本文链接: http://hellofrank.github.io/2018/04/27/Git-Rebase-黄金法则问题/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

Github的webhooks网站自动化部署

Github的webhooks进行网站自动化部署

image.png

相信很多码农都玩过了Git,如果对Git只是一知半解,可以移步LV写的 GIT常用操作总结,下面介绍到的一些关于 Git 的概念就不再赘述。

为啥想写这篇文章?主要是因为部门服务器因为安全性原因不允许SCP上传文件进行应用部署,然后有一些应用是放在Github上的,然后部署应用的步骤就变成:

1.git clone github项目 本地目录
2.配置一下应用的pm2.json并reload
3.Nginx配置一下反向代理并restart

当然如果只是一次性部署上去就不再修改的话并没啥问题,但是要是项目持续性修改迭代的话,就比较麻烦了,我们就在不断的重复着上面的步骤。作为一个码农,怎么允许不断的重复同样的工作,于是Github webhooks闪亮登场。

关于Github webhooks

  • 必须是Github上面的项目
  • 订阅了确定的事件(包括push/pull等命令)
  • 自动触发

刚好符合了这几个条件,那接下来就看看如何进行网站自动化部署,主要会从下面几点来讲解:

  1. 自动化shell脚本
  2. 服务端实现
  3. 配置github webhooks

自动化脚本

auto_build.sh

1
2
3
4
5
6
7
#! /bin/bash
SITE_PATH='/root/nginx/www'
cd $SITE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master

Note: 在执行上面shell脚本之前我们必须第一次手动git clone项目进去

服务端实现

Github webhooks需要跟我们的服务器进行通信,确保是可以推送到我们的服务器,所以会发送一个带有X-Hub-Signature的POST请求,为了方便我们直接用第三方的库github-webhook-handler来接收参数并且做监听事件的处理等工作。

1
npm i github-webhook-handler -S

index.js

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
var http = require('http');
var spawn = require('child_process').spawn;
var createHandler = require('github-webhook-handler');

// 下面填写的myscrect跟github webhooks配置一样,下一步会说;path是我们访问的路径
var handler = createHandler({ path: '/auto_build', secret: '' });

http.createServer(function (req, res) {
handler(req, res, function (err) {
res.statusCode = 404;
res.end('no such location');
})
}).listen(6666);

handler.on('error', function (err) {
console.error('Error:', err.message)
});

// 监听到push事件的时候执行我们的自动化脚本
handler.on('push', function (event) {
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref);

runCommand('sh', ['auto_build.sh'], function( txt ){
console.log(txt);
});
});

function runCommand( cmd, args, callback ){
var child = spawn( cmd, args );
var response = '';
child.stdout.on('data', function( buffer ){ resp += buffer.toString(); });
child.stdout.on('end', function(){ callback( resp ) });
}

// 由于我们不需要监听issues,所以下面代码注释掉
// handler.on('issues', function (event) {
// console.log('Received an issue event for %s action=%s: #%d %s',
// event.payload.repository.name,
// event.payload.action,
// event.payload.issue.number,
// event.payload.issue.title)
});

配置github webhooks

image.png

小结

上面就是利用Github webhooks进行网站自动化部署的全部内容了,不难发现其实这项技术还是有局限性的,那就是依赖于github,一般我们选择的都是免费github账号,所有项目都对外,一些敏感项目是不适合放置上去的。

git教程

名称

git - 愚蠢的内容跟踪器

概要

git [--version] [ -  help] [-C <path>] [-c <name> = <value>]
    [--exec-path [= <path>]] [--html-path] [--man-path] [--info-path]
    [-p | --paginate | -P | --no-pager] [ -  no-replace-objects] [--bare]
    [--git-dir = <path>] [ -  work-tree = <path>] [--namespace = <name>]
    [--super前缀= <路径>]
    <command> [<args>]

描述

Git是一个快速,可扩展的分布式版本控制系统,具有异常丰富的命令集,可提供高级操作和对内部的完全访问。

请参阅gittutorial [7]以开始使用,然后查看 giteveryday [7]以获取有用的最小命令集。在Git的用户手册有一个更深入的介绍。

掌握了基本概念后,您可以回到此页面了解Git提供的命令。您可以使用“git help command”了解有关各个Git命令的更多信息。 gitcli [7] 手册页概述了命令行命令语法。

可以在以下位置查看最新Git文档的格式化和超链接副本https://git.github.io/htmldocs/git.html。

OPTIONS


  • 打印git程序来自的Git套件版本。

  • 救命
    打印概要和最常用命令的列表。如果选择–all或-a已给出,则打印所有可用命令。如果命名了Git命令,则此选项将显示该命令的手册页。

其他选项可用于控制手册页的显示方式。有关更多信息,请参阅git-help [1],因为git –help …内部转换为git help …。

-C <路径>
运行就好像git是在而不是当前工作目录中启动的。当-C给出多个选项时,-C 相对于前面的每个后续非绝对值被解释-C 。如果存在但是为空,例如-C “”,则保持当前工作目录不变。

此选项会影响预期的路径名的选项一样–git-dir,并 –work-tree在他们的路径名的解释,将相对于所造成的工作目录进行-C选择。例如,以下调用是等效的:

git --git-dir = a.git --work-tree = b -C c status
git --git-dir = c / a.git --work-tree = c / b status

-c =
将配置参数传递给命令。给定的值将覆盖配置文件中的值。的格式与git config列出的格式相同 (以点分隔的子键)。

请注意,允许省略=in git -c foo.bar …并设置 foo.bar为布尔值true(就像[foo]bar在配置文件中一样)。包括equals但空值(如git -c foo.bar= …)设置foo.bar为git config –type=bool将转换为的空字符串false。

–exec路径[= <路径>]
安装核心Git程序的路径。这也可以通过设置GIT_EXEC_PATH环境变量来控制。如果没有给出路径,git将打印当前设置然后退出。

–html路径
打印路径,不带斜杠,安装Git的HTML文档并退出。

–man路径
打印manpath(请参阅参考资料man(1))获取此版本Git的手册页并退出。

–info路径
打印安装记录此版本Git的Info文件的路径并退出。

-p
–paginate
如果标准输出是终端,则将所有输出传输到较少(或如果设置为$ PAGER)。这将覆盖pager. 配置选项(请参阅下面的“配置机制”部分)。

-P
–no寻呼机
不要将Git输出传输到寻呼机。

–git-DIR = <路径>
设置存储库的路径。这也可以通过设置GIT_DIR环境变量来控制。它可以是当前工作目录的绝对路径或相对路径。

  • 共同努力树= <路径>
    设置工作树的路径。它可以是绝对路径或相对于当前工作目录的路径。这也可以通过设置GIT_WORK_TREE环境变量和core.worktree配置变量来控制(有关更详细的讨论,请参阅git-config [1]中的core.worktree )。

–namespace = <路径>
设置Git名称空间。有关更多详细信息,请参阅gitnamespaces [7]。相当于设置GIT_NAMESPACE环境变量。

–super前缀= <路径>
目前仅供内部使用。设置一个前缀,该前缀提供从存储库上方到其根目录的路径。一个用途是给出调用它的超级项目的子模块上下文。


  • 将存储库视为裸存储库。如果未设置GIT_DIR环境,则将其设置为当前工作目录。

–no替换对象
不要使用替换引用来替换Git对象。有关更多信息,请参阅 git-replace [1]。

–literal按本义,pathspecs
按字面意思处理pathspecs(即没有globbing,没有pathspec魔法)。这相当于将GIT_LITERAL_PATHSPECS环境变量设置为1。

–glob-pathspecs
为所有pathspec添加“glob”魔法。这相当于将GIT_GLOB_PATHSPECS环境变量设置为1。可以使用pathspec magic“:( literal)”在各个pathspec上禁用通配符

–noglob-pathspecs
为所有pathspec添加“literal”魔法。这相当于将GIT_NOGLOB_PATHSPECS环境变量设置为1。可以使用pathspec magic“:( glob)”在各个pathspec上启用globbing

–icase-pathspecs
为所有pathspec添加“icase”魔法。这相当于将GIT_ICASE_PATHSPECS环境变量设置为1。

–no-可选锁
不要执行需要锁定的可选操作。这相当于设置GIT_OPTIONAL_LOCKS为0。

–list-CMDS =基团[,组…]
按组列出命令。这是一个内部/实验选项,可能会在将来更改或删除。支持的组包括:builtins,parseopt(使用parse-options的内置命令),main(libexec目录中的所有命令),其他(所有其他命令$PATH都有git-前缀),list- (请参阅命令中的类别 - list.txt),nohelpers(排除帮助程序命令),别名和配置(从配置变量completion.commands检索命令列表)

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×