git使用方法简明教程 - 团队篇

简述

首先,如果你没有看过前文。我推荐你先看一下我的上一篇文章git使用方法简明教程 - 个人篇,这样你能对git这个程序员必用的软件能够有一定的了解。

工作流

团队使用代码进行协作编程与个人使用不太一样。因为它一般来说是在多个分支上进行操作。这里涉及到一个分支(branch的概念,我稍后再讲)

一般来说一个团队的代码仓库至少会有2个以上的分支。有一个生产环境的master (或者release) 分支,一个用于内部内部开发的dev分支。
有两种模式,一种是小团队的快速开发。多个人在同一个分支开发。通过不断地进行push和pull进行代码间的同步。另一种是以开发分支为基础。每个人分出一个自己的分支,完成开发后合并到主开发分支。这种情况可以根据实际需求选择一个人一个个人分支或者一个人开发一个任务就分出一个分支两种情况。

分支

分支,英文名branch。可以通过git branch命令查看本地的分支。
使用git checkout [分支名]的方式来切换不同分支。
我们在使用git log命令查看提交简述的时候也能看到分支所在位置。

分支分为本地分支和远程分支。远程分支是远程代码仓库在本地的映射。我们可以通过git fetch命令进行同步本地的远程分支。通过git branch -r命令可以查看所有的远程分支。
我们正常操作都是操作的本地分支。

通过git checkout -b [新分支名]就可以从当前位置创建一个新的分支。并且切换到新的分支上来。
在完成代码编辑的时候我们可以通过git merge命令进行分支的合并操作。
举例:
我有两个分支masterdev.分别是主分支和开发分支。我在开发分支上完成了一些代码的提交后。想要把dev分支的变更合并到主分支

1
2
$ git checkout master
$ git merge dev

如果有代码冲突的情况我们需要解决冲突,然后使用git commit命令提交合并
如果在代码冲突的过程中想要中断代码合并的过程,使用git merge --abort命令

代码冲突

代码冲突是多人协作时常见的问题,因为你没法保证在你进行编辑的时候其他的不会对代码进行修改。在大多数情况下git会自动处理代码变更。但如果两个开发者共同修改了同一处代码时。git无法自动处理。那么就需要开发者手动解决冲突。
当git出现无法处理的冲突时,它会告知你冲突的文件,并修改文件共同修改处的代码变更为:

1
2
3
4
5
<<<<<<<head
这里是当前代码
=======
这里是远程代码
>>>>>>>xxxxxxxxxx(发生冲突的hash值)

当出现这种情况时,作为开发者你需要做的是仔细比较两边的代码,并把多余的东西删除。然后把所有的冲突全部解决完毕后,提交代码。

rebase

NOTE:rebase是一种破坏性的行为, 请尽量不要在公共分支上进行操作

当我们在自己的分支提交了一系列代码后,需要把完成的功能提交到公共开发分支,那么我们要做的第一步是先把公共分支的代码同步到我们自己的分支。简单的,我们当然可以使用git merge命令。但是,这样会留下一个git生成的merge commit点,而这个commit是无意义的。对于code review(代码审查)来说是一个比较影响的东西。当然了,merge commit 点的好处是所有的操作都是线性的。在进行合并个人分支到公共分支的过程中最好使用merge,而把公共分支同步到个人分支的时候,我建议使用git rebase, 他能让你看上去是从当前公共分支创建出来的个人分支进行往前编辑
rebase的原理是把往前一段距离的代码提交重新打开,然后重新提交一遍。因为是一种破坏性的行为,因此无法与远程服务器同步,需要使用git push -f命令强制覆盖远程分支。

举例:
我有一个个人开发的分支moonrailgun, 然后有一个开发分支dev。在经过一段时间的开发后,两个分支各向前跑了几个commit。现在我希望能够把我的moonrailgun合并到dev分支。为了保证冲突能现在我的个人分支解决,我需要先把dev的变更同步到moonrailgun分支

1
2
# 当前在moonrailgun分支
$ git rebase dev

如果出现冲突。需要解决冲突,然后git add以后使用git rebase --continue命令继续操作。
如果想要中断rebase的过程,使用git rebase --abort

然后你就能很方便的把moonrailgun分支合并到dev分支上了,并且代码的历史线会很干净。

P.S.: 如果团队在分支上进行代码操作,那么常常会出现代码不同步的问题。那么为了保证代码分支线的干净。最好不要使用git pull命令(因为这会留下一个合并的commit点)。推荐的操作如下:

1
2
3
4
$ git fetch
$ git log origin/master
# 查看最新的远程commit的hash值。复制下来
$ git rebase <hash>

这样可以完美的处理单分支多用户进行代码提交。

Vue学习笔记

概述

本章内容主要记录一些在Vue开发过程中比较实用的一些工具,写法之类的东西

本章内容可能会不断、不定期的进行更新。

工具

好用的UI框架: elementUI

写法

根据字符串动态生成不同组件:is属性
通过is属性我们可以做一些比较特殊的定制化操作。比如我们可能定义一系列的控件,然后根据后台返回的表单对象自由组合成对应的表单。

状态管理

除了常见的Vuex以外。Vue+RxJS+VueRx 这套技术栈也是一个不错的选择

如何实现方法既能实现函数式编程又能获取结果进行比较——实现形如add(1)(2)(3)...(n)的方法

面试的时候面试官出了一道题目很有意思。问的是这样的。假如我有一个方法add。如何实现形如add(1)(2)调用返回3
这道题答案很简单,如下:

1
2
3
4
5
function add (x) {
return function (y) {
return x + y;
}
}

但我当时第一时间的反应是这样的: 如何实现形如add(1)(2)(3)...(n)这样的链式调用。
首先这个问题有两个难点:

  • 1.如何解决累加结果的存储问题
  • 2.如何解决他返回的方法可以作为结果来使用

首先这第一个问题是好解决的。只需要在内部存储计数器即可。而第二个问题是无法完全解决的。因为如果要实现链式调用那么返回必须是函数。而函数的typeof值是function, 永远不能作为一个number使用。但是如果放宽限制。我们可以用过重写方法的toString函数来实现对一些隐式调用转换为字符串的匹配。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var sum = 0;
function add(x) {
sum += x;
return add;
}
add.toString = function() {
return sum;
}

var result = add(1)(2)(3);
console.log(typeof result); // 返回function
console.log(result + ''); // 返回6
console.log(result == 6); // 返回true

当然,这里有个问题。就是封装性不好。会污染全局变量。那么我们把add方法做一下闭包处理进行优化一下:

1
2
3
4
5
6
7
8
9
10
11
function add(x) {
var sum = x;
function tmp(y) {
sum += y;
return tmp;
}
tmp.toString = function() {
return sum;
}
return tmp;
}

Firefox、safari的session无法匹配的原因

场景

在测试服务器上出现一个这样奇怪的场景:在Firefox和Safari浏览器上出现session无法正确被识别,而Chrome浏览器能够正常被服务器识别session。

原因

服务端时间与客户端时间不匹配,客户端时间在服务端时间后并差距大于session过期时间(如session过期时间为30分钟, 那么客户端时间往后调30分钟以上或者服务端时间往前调30分钟以上都会出现这个问题)

分析

首先我们看一下以下两张图:

[图1]


[图2]

其中图1是我在火狐浏览器发起的一次http请求的请求头,图2是我在chrome浏览器中发起的http请求的请求头
可以见当cookie过期的时候火狐浏览器发送的请求头中会自动过滤掉已经过期的cookie,而Chrome浏览器则不会。而我们知道服务端的session是根据浏览器发送的cookie进行匹配的。因此火狐浏览器当客户端时间与服务端时间差距过大的时候会出现session无法正常匹配的情况

同理,Safari也会过滤掉失效的cookie。

解决方案

暂时没有比较好的解决方案,只能确保服务端的时间是正常的即可。

nginx使用笔记

简介

主要记录一些使用nginx的一些特殊的技巧。常用的不会记录在内

技巧

使用rewrite重定向时保留referer网站来源

首先我们要知道referer是浏览器主动发起时带入的。跟服务端无关。而浏览器在进行rewrite重定向时并不会带入referer,而目前没有成熟的解决方案。这里记录一个骚操作: 通过cookie来进行同域之间的referer传递

比如我有一个页面www.moonrailgun.com,我想检测当用户是手机端访问时跳转到m.moonrailgun.com
那么要这么做:

1
2
3
4
5
6
7
8
#在www.moonrailgun.com把referer数据写入cookie:
add_header Set-Cookie "referer=$http_referer;Domain=moonrailgun.com";

#在m.moonrailgun.com把referer数据根据cookie信息重新构造出来:
if ($http_cookie ~* "referer=(.+?)(?=;|$)") {
set $referer_cookie $1;
}
proxy_set_header Referer $referer_cookie;

ReactNative踩坑记录与学习笔记

原生交互

  • 在iOS9之后,网络请求默认为Https请求,如需支持Http,修改info.plist文件添加键值对设置允许http访问
    /images/react/001.png
  • 编译后抛出错误$export is not a function,原因: react-native 无法正常使用babel的runtime-transform插件,原因不明
  • react-native安卓端允许的最大长计时器时间为60000ms,而socket.io默认ping计时器为85000ms.为了解决这个警告你需要在服务端设置pingInterval(默认25000)pingTimeout(默认60000)使两者之和小于等于60000ms

路由react-navigation

Github

  • 路由插件解析需要依赖babel-preset-react-native插件:确保.babelrc文件中有"presets": ["react-native"]。否则会抛出语法错误
  • 当使用redux嵌套多个Navigator的时候。如果外面是一个StackNavigator然后子路由是一个DrawerNavigatorTabNavigator会抛出异常Cannot read property 'undefined' of undefined。解决方案:react-navigation#issues#1919

FlatList

不要把Array.reverse()和inverted一起使用! 更新时会有问题! 选一个即可

编译打包

安卓: cd android && ./gradlew assembleRelease

  • 当使用64位linux系统打包时抛出找不到aapt, 如果该路径下有aapt文件的话那么则是64位系统的问题。apktool需要32位编译环境。安装ia32-libs即可解决问题,如为centos则使用命令yum install libstdc++.i686 glibc.i686 zlib.i686
  • 如出现:app:bundleReleaseJsAndAssets 错误。可能是由于系统配置过低导致的编译文件超时的问题。解决方案是手动编译js文件后再打包(使用-x ":app:bundleReleaseJsAndAssets"参数跳过)
    1
    2
    3
    4
    > mkdir -p android/app/build/intermediates/assets/release
    > mkdir -p android/app/build/intermediates/res/merged
    > node node_modules/react-native/local-cli/cli.js bundle --platform android --dev false --reset-cache --entry-file src/app/index.js --bundle-output android/app/build/intermediates/assets/release/index.android.bundle --assets-dest android/app/build/intermediates/res/merged/release
    >

测试环境使用独立包名(Android)

android/app/build.gradle

1
2
3
4
5
6
7
android {
buildTypes {
debug {
applicationIdSuffix ".test"
}
}
}

即在debug模式下。为包名增加后缀.test

在gradle.properties中保存敏感信息

因为gradle.properties可能会同时存在项目需要的信息与敏感信息。为了不把敏感数据上传到版本控制仓库,可以考虑使用git的命令

1
git update-index --assume-unchanged android/gradle.properties

使用方式是先提交需要上传的部分,然后执行上述命令即可

撤销标识

1
git update-index --no-assume-unchanged android/gradle.properties

升级到新版本

使用自动迁移脚本

1
npx react-native upgrade [version]

手动迁移

查看迁移网站https://react-native-community.github.io/upgrade-helper/

Linux常用命令记录

简介

主要是为了记录一下linux使用过程中常用的命令。方便日后检索

快捷键

  • ctrl+z 将当前任务暂停,回到终端页面。可以使用fg回到任务或使用bg将当前任务挂到后台

常用命令

  • cp from to 复制
  • mv from to 移动
  • rm file 删除
  • cat file 输出文件
  • pwd 输出当前工作空间
  • who 当前登录所有用户
  • whoami 当前登录用户名
  • wget url 下载文件
  • curl url 发送请求
  • free -h 查看系统内存
  • df -h 查看硬盘空间
  • du -h ./ 查看文件占用
  • tail -f 持续跟踪文件
  • uname -a 查看系统信息
  • netstat -tulpn 查看系统网络情况
  • lsof -i:80 查看系统端口监听
  • grep -r "str" ./ 在文件中查找字符串
  • find ./ -name filename 在路径下根据文件名查找文件
  • top 任务管理器
  • uptime 启动时间,登录用户数,系统资源占用率
  • kill -9 pid 杀死进程
  • ps aux | grep name 查看某进程情况
  • nohup command & 后台运行某命令
  • scp [[[email protected]]host1:]file1 [[[email protected]]host2:]file2 ssh cp
  • su username 切换用户

有用但不常用命令

  • mount --bind test1 test2 挂载文件
  • tree 生成文件结构
  • history 查看用户历史命令
  • last 查看用户登录记录
  • lastb 查看用户登录失败记录
  • dmesg 查看系统诊断日志
  • dd if=/dev/zero of=/root/swapfile bs=1M count=1024 创建一个1024*1M大小的文件。位置为of,内容为if
  • mkswap /root/swapfile 创建交换空间
  • swapon /root/swapfile 开启交换空间

压缩

  • tar -cvf jpg.tar *.jpg 将目录里所有jpg文件打包成tar.jpg
  • tar -czf jpg.tar.gz *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz
  • tar -cjf jpg.tar.bz2 *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2
  • tar -cZf jpg.tar.Z *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z
  • rar a jpg.rar *.jpg rar格式的压缩,需要先下载rar for linux
  • zip jpg.zip *.jpg zip格式的压缩,需要先下载zip for linux

解压

  • tar -xvf file.tar 解压 tar包
  • tar -zxvf file.tar.gz 解压tar.gz
  • tar -jxvf file.tar.bz2 解压 tar.bz2
  • tar -Zxvf file.tar.Z 解压tar.Z
  • unrar e file.rar 解压rar
  • unzip file.zip 解压zip

微信开发踩过的坑

JSSDK

  • 微信使用方法wx.config时需要输入appid, 否则会直接抛出config:fail而不会有具体的错误提示。如果你的应用的appid来源比较复杂的话有必要检查一下appid
  • 微信在分享时如果link参数非法, 则会出现debug内容一切 正常 但是无法正常进行分享内容自定义。

Linux服务安全——记一次网络攻击

背景

使用linode服务器第二天就经历一次网络攻击,对方通过暴力破解root账号成功攻陷了我密码强度相对较低的服务器并通过我的服务器向外发起DDOS攻击导致在2小时间流失上行流量500G。造成了相当的损失

日志查询

1
# lastb

lastb命令查询试图通过SSH访问服务器密码失败的记录。可以查询到有来自印度,韩国与一个不知名国家的ip的重复尝试请求,由于访问次数多、频率高,可以看出是通过脚本来实现暴力破解的行为

1
# last

last 查询登录记录,在登录记录中查看到在事发时间没有任何登录请求。可能原因有二:

  • 对方在拿到root权限账号后清除了自己的登录记录
  • 对方在之前就拿到了root权限并留下了木马之类的后门,在事发时间通过服务端口远程访问

同时可以通过查看/var/log/secure日志文件查询用户登录记录

安全策略

https://www.linode.com/docs/security/securing-your-server/
https://www.cnblogs.com/alimac/p/5848372.html

相关命令

1
2
3
4
5
# 查看当前网络服务
sudo netstat -tulpn

# 重启sshd
sudo service sshd restart

解决方案

  • yum update
  • 增加第二管理员账号
  • 增加第二管理员sudo权限
  • 禁止root用户直接通过ssh登录
  • 关闭密码登录,使用秘钥对登录
  • 配置iptables(可选)

.ssh文件权限

  • 700 .ssh
  • 600 authorized_keys

python学习笔记

Flask

flask是一个轻量级的web框架。

PIL 相关内容

  • 混合半透明图片与半透明图片时会出现中空透明项目的问题

    imlayer 为两张半透明图,如下图所示:

    im(100x100)

    layer(100x100)

    执行:

    1
    im.paste(layer, mask=layer)

    返回

    会发现里面有透明像素,而不是我们想要的layer叠加到im上的效果
    这是因为layer本身拥有一个渐变的alpha通道,通过mask指定的alpha通道蒙版会在im抠出一个渐变的圆形。然后再把拥有渐变效果的layer叠加到im上。
    这就相当于在两个地方处理了两次透明处理。解决方法很简单,就是在粘贴layer的时候丢弃掉它的alpha通道即可

    返回