Redis消息队列实现

消息队列

某次在某乎上看到有人提到消息队列的问题,然后有人在回答里提到了Redis,接着便有人在评论里指出:Redis是缓存,不是消息队列。

但不幸的是,Redis的确提供一个简易的消息队列机制,可以用于一些要求不那么高的场合。

方法就是利用Redis的列表类型的push和pop操作。

我对前文所介绍的Redis Cache作了一点简单的扩展,增加了消息队列功能。

实现

代码基本就这么点:

class RedisMQ(RedisCache):
    def __init__(self, dbname, host='localhost', port=6379, db=0):
        super(RedisMQ, self).__init__(dbname, host, port, db)

    def push(self, channel, data):
        ch = self._getkey("channel", channel)
        self.db.lpush(ch, self.SERIALIZER.dumps(data))

    def pop(self, channel, timeout=5):
        ch = self._getkey("channel", channel)
        msg = self.db.brpop(ch, timeout)
        return self.SERIALIZER.loads(msg[1]) if msg else None


class Channel(object):
    MQ = RedisMQ("msgqueue")

    def __init__(self, channel):
        self.channel = channel

    def push(self, **kwargs):
        Channel.MQ.push(self.channel, kwargs)

    def pop(self):
        return Channel.MQ.pop(self.channel)

用法

消息生产者

ch = Channel("test")
ch.push(a=123,b="hello")

消息消费者,可能是另一个线程,甚至是另一个进程,甚至是另外一台主机——只要它们共用同一个redis即可。

ch = Channel("test")
while msg=ch.pop():
    # msg: {"a": 123, "b": "hello"}
# ch is empty

CentOS7配置redis主从复制方法

1. 准备好4台机器

192.168.42.150 redis-node1 #主
192.168.42.151 redis-node2 #从 
192.168.42.152 redis-node3 #从
192.168.42.153 redis-node4 #从

将主机解析写入hosts文件,分发至每台机器

2. 安装redis,配置好基本配置

(1) 4台机器,分别安装redis

cd /usr/local/src
wget http://192.168.42.26/install_package/down/redis-3.2.3-1.el7.x86_64.rpm
yum install redis-3.2.3-1.el7.x86_64.rpm -y

(2) 4台机分别配置好,配置文件,做好备份

cp /etc/redis.conf{,.back}
vim redis.conf
daemonize yes
bind 192.168.42.150  #改为各个节点的IP

(3) 依照上面设定的从主机,在从主机配置文件中开启从配置(需要配置3台机器)

# slaveof <masterip> <masterport>
slaveof  192.168.42.150 6379

(4) 启动redis-server(4台同时启动)

redis-server /etc/redis.conf

(5) 在主机器上登录redis

[root@redis-node1 ~]# redis-cli -h 192.168.42.150
192.168.42.150:6379&gt; 
192.168.42.150:6379&gt; keys *
1) "magedu"
192.168.42.150:6379&gt; 
192.168.42.150:6379&gt; set ok "verygood!!!"
OK
192.168.42.150:6379&gt; get ok
"verygood!!!"
192.168.42.150:6379&gt;

登录其他3台从服务器

redis-cli -h 192.168.42.151
redis-cli -h 192.168.42.152
redis-cli -h 192.168.42.153
拿153做示例:
[root@redis-node4 src]# redis-cli -h 192.168.42.153
192.168.42.153:6379&gt; keys *
1) "magedu"
192.168.42.153:6379&gt; 
192.168.42.153:6379&gt; get ok
"verygood!!!"
192.168.42.153:6379&gt;

至此为至redis主/从已经实现,在主节点上查看信息

192.168.42.150:6379&gt; INFO Replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.42.151,port=6379,state=online,offset=22806,lag=1
slave1:ip=192.168.42.152,port=6379,state=online,offset=22806,lag=1
slave2:ip=192.168.42.153,port=6379,state=online,offset=22806,lag=1
master_repl_offset:22806
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:22805

接下来在四个结点上配置sentinel,实现故障转移。此处实现累似于MariaDB的MHA 在上面我们已经配置好主从复制集群,现在我们需要添加一台机器[192.168.42.154]来做高可用 同样我们需要设置好,IP,主机名,下载安装redis

192.168.42.154 redis-sentinel  #将主机解析追加至其他的4台的hosts文件中,本机也需要一份
cd /usr/local/src
wget http://192.168.42.26/install_package/down/redis-3.2.3-1.el7.x86_64.rpm
yum install redis-3.2.3-1.el7.x86_64.rpm -y

(1)配置sentinel

# sentinel monitor     #法定人数
cp /etc/redis-sentinel.conf{,.back}
vim /etc/redis-sentinel.conf

daemonize yes
sentinel monitor mymaster 192.168.42.150 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 18000
sentinel auth-pass mymaster centos.123 #这是认证选项,我们这里的主节点并没有开启认证

(2)启动sentinel

redis-sentinel /etc/redis-sentinel.conf

查看端口是否已经启动

[root@redis-sentinel src]# ss -tnl
State      Recv-Q Send-Q  Local Address:Port                 Peer Address:Port              
LISTEN     0      128                 *:22                              *:*                  
LISTEN     0      100         127.0.0.1:25                              *:*                  
LISTEN     0      511                 *:26379                           *:*                  
LISTEN     0      128                :::22                             :::*                  
LISTEN     0      100               ::1:25                             :::*                  
LISTEN     0      511                :::26379                          :::*

(3)模拟故障:

192.168.42.150:6379
pkill redis
#查看
[root@redis-node1 ~]# ss -tnl
State      Recv-Q Send-Q                             Local Address:Port                                            Peer Address:Port              
LISTEN     0      128                                            *:22                                                         *:*                  
LISTEN     0      100                                    127.0.0.1:25                                                         *:*                  
LISTEN     0      128                                           :::22                                                        :::*                  
LISTEN     0      100                                          ::1:25

(4)查看故障是否转移

登录192.168.42.151:6379 #巧了,恰好151变成主了
192.168.42.151:6379&gt; 
192.168.42.151:6379&gt; INFO Replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.42.153,port=6379,state=online,offset=5413,lag=1
slave1:ip=192.168.42.152,port=6379,state=online,offset=5413,lag=2
master_repl_offset:5413
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:5412
192.168.42.151:6379&gt; 

登录192.168.42.152:6379查看,的确是151变成主了
192.168.42.152:6379&gt; INFO Replication
# Replication
role:slave
master_host:192.168.42.151
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:11402
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
192.168.42.152:6379&gt;

(4)我们再把151的进程杀了,再来看一次,可以看到只有一主一从了

192.168.42.152:6379&gt; INFO Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.42.153,port=6379,state=online,offset=1625,lag=1
master_repl_offset:1768
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1767
192.168.42.152:6379&gt;

(5)最后我们将杀死的两台redis恢复,再来查看

192.168.42.152:6379&gt; INFO Replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.42.153,port=6379,state=online,offset=12763,lag=1
slave1:ip=192.168.42.151,port=6379,state=online,offset=12763,lag=1
slave2:ip=192.168.42.150,port=6379,state=online,offset=12763,lag=0
master_repl_offset:12763
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:12762
192.168.42.152:6379&gt; 

可以看出此时的1主3从又回来了,不过此时主节点,是152

回到150,和151的节点查看效果
192.168.42.150:6379&gt; INFO Replication
# Replication
role:slave
master_host:192.168.42.152
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:23555
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
192.168.42.150:6379&gt; 



192.168.42.151:6379&gt; INFO Replication
# Replication
role:slave
master_host:192.168.42.152
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:20782
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

接下来我们配置有密码认证的主从和高可用

我们之前在配置sentinel,时还记得 #法定人数吗,判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行

    sentinel monitor #法定人数

我们现在将154这台干脆也做成redis的从服务器,而sentinel,是这5台的集合(150,151,152,153,154)

(1).将153的配置文件推到154一份

scp /etc/redis.conf{,.back} [email protected]:/etc/
 到154这边稍微修改一下
 vim /etc/redis.conf
 bind 192.168.42.154

因此这次我们是要做密码认证的,因此5台机器都需要加上密码

(2).我们现在查看之前做了 sentinel后,配置文件系统自动帮我们改了,现在我们要恢复到初始状态,重新来过

所有的配置文件还需要设置我们的密码(为了方便管理,我们这里统一设置成magedu) requirepass magedu

所有从节点加上

#masterauth 
masterauth magedu
slaveof 192.168.42.150 6379

(3).密码设置好之后,启动所有服务

redis-server /etc/redis.conf
ss -tnl

登录150,需要认证了

[root@redis-node1 ~]# redis-cli -h 192.168.42.150
192.168.42.150:6379&gt; keys *
(error) NOAUTH Authentication required.

[root@redis-node1 ~]# redis-cli -h 192.168.42.150
192.168.42.150:6379&gt; keys *
(error) NOAUTH Authentication required.
192.168.42.150:6379&gt; keys *
(error) NOAUTH Authentication required.
192.168.42.150:6379&gt; AUTH magedu
OK

同样的,我们需要登录认证其他机器

再150机器上设置key
192.168.42.150:6379&gt; set zlyc "zai lai yi ci"
OK
192.168.42.150:6379&gt; get zlyc
"zai lai yi ci"
192.168.42.150:6379&gt; 

其他机器读取OK
192.168.42.151:6379&gt; get zlyc
"zai lai yi ci"
192.168.42.151:6379&gt;

解决phpmyadmin出现The mbstring extension is missing错误方法

这篇文章主要介绍了phpmyadmin提示The mbstring extension is missing的解决方法,分析了错误提示的原因与不同平台的解决方法,具有一定的参考借鉴价值,需要的朋友可以参考下

一、问题:

phpmyadmin提示:The mbstring extension is missing. Please check your PHP configuration.

二、解决方法:

其实只要运行一段:

yum install php-mbstring

就OK了。

如果用的是linux的话,可能是这个问题:查看一下 /etc/php5/mods-available/json.ini 这个文件,把第二行开头的分号去掉,也就是去掉注释,然后保存,重启php就可以了。

ubuntu mysql远程连接+phpmyadmin安装

一、如何让ubuntu上的mysql允许远程连接

进入MySQL,执行如下命令:

use mysql;

GRANT ALL PRIVILEGES ON *.* TO 'username'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

flush privileges; //刷新

select host,user from user; //查看是否成功

退出mysql;

  • 打开sudo vim /etc/mysql/my.cnf(可能不是此路径,也可能是my。conf,在该目录下找一下)
  • 将bind-address = 127.0.0.1
  • 设置成bind-address = 0.0.0.0(设备地址)

重新启动(命令如下):

sudo /etc/init.d/mysql restart

这样就可以远程连接了!

二、ubuntu如何安装phpmyadmin

方法一:

在phpmyadmin官网(https://www.phpmyadmin.net/)上下载压缩包,解压至你apache根目录下(默认/var/www/html),重命名为phpmyadmin;

sudo apt-get install php-mbstring php-gettext

然后修改PHP配置文件:

sudo vim /etc/php/7.0/apache/php/ini
display_errors = On(都改为On)
extension=php_mbstring.dll (去掉前面的;)

重启apache:

sudo /etc/init.d/apache2 restart

可以用http://localhost/phpmyadmin访问了!

方法二:

sudo apt-get install phpmyadmin

建立/var/www/html 下的软连接:

sudo ln -s /usr/share/phpmyadmin /var/www/html/phpmyadmin

安装php-mbstring和php.ini配置同方法一。

ubuntu14.04配置apache2 svn服务器(提供https访问)

一. 安装PHP

sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt php5-curl php5-imagick php5-cli

二. 安装svn

输入安装命令:

sudo apt-get install subversion

(由于阿里云远程链接服务器时默认登陆管理员账号,所以sudo可以不用)
(如果无法下载软件,可能是由于阿里云可能把更新源的位置改了,运行apt-get update就行)

之后选择SVN服务文件及配置文件的放置位置。我放在了/srv下的svn目录。

sudo mkdir /srv/svn(版本仓库test)

目录建好后,创建版本仓库

sudo svnadmin create /srv/svn/test

执行之后test下文件结构如下:

未分类

三. 配置svn

跳转到配置文件

sudo cd /srv/svn/test/conf

1.修改svnserver.conf

sudo vi svnserve.conf
[general]
#匿名用户不可读
anon-access = none
#权限用户可写
auth-access = write
#密码文件为passwd
password-db = passwd
#权限文件为authz
authz-db = authz

这里修改时要顶格,不然要报错

2.authz 制定管理员组
即admin组的用户为admin,admin组对test有rw(读写权限)

[groups]
admin=admin       ##可以admin=admin,admin2,admin3

[test:/]
@admin=rw       ##admin组对test下的文件有读写权限

[:/项目/目录] #是以项目名作为第一个单位。不写版本库可以省略‘:’,即写成[/]
权限主体可以是用户组、用户或,用户组在前面加@,表示全部用户。权限可以是w、r、wr和空,空表示没有任何权限。

3.编制passwd文件,设定用户密码

[users]
admin=admin       ##用户名=密码

(注意等号两边不要留空格)

4.启动svn服务器

sudo svnserve -d -r /srv/svn/ --listen-port 3690

(这里启动服务时务必以管理员权限启动,否则用户拉取、提交文件时会提示权限不够)

-d 以守护模式启动

-r 制定svn版本库根目录,这样是便于客户端不用输入全路径,就可以访问版本库了

–listen-port 3690 监听3690端口,默认就是3690。。。所以不输也可以

5.访问代码库

svn://your ip/test
(查看IP地址:ifconfig)

注:到这里位置就可以通过svn访问了,通过https访问在后面

四. 安装apache2

输入安装命令:

sudo apt-get install apache2 apache2-utils libapache2-svn
sudo a2enmod ssl 开启SSL模块
sudo a2ensite default-ssl 启用SSL站点支持
sudo a2enmod rewrite 启用rewrite模块

1.配置/etc/apach2/apache2.conf

sudo vi /etc/apache2/apache2.conf

增加对.htaccess的支持:将www目录的AllowOverride参数修改为ALL
防止访问目录:将Options中的Indexes删除

2.重启apache服务

sudo /etc/init.d/apache2 restart

Apache的默认安装,会在/var下建立一个名为www的目录,这个就是Web目录了

  • 默认站点: /var/www/
  • 配置目录: /etc/apache2/
  • 日志目录: /var/log/apache/
  • 启动脚本: /etc/init.d/apache2

五. 配置自动更新

这里配置自动更新用的是svn的钩子,脚本是shell,也可以用其他的脚本比如python
钩子脚本的具体写法就是操作系统中shell脚本程序的写法,请根据自己SVN所在的操作系统和shell程序进行相应的写作
实现原理:当用户提交commit动作发生都让另外一处project马上从仓库中进行代码checkout一份出来!

1.在Web目录迁出代码

sudo svn co svn://127.0.0.1/test /var/www/html --username admin --password admin

2.添加脚本

在svn项目的hooks文件夹中的post-commit文件中添加脚本:用vi命令编辑一个新的post-commit(看清楚没有后缀名)千万不要用hooks文件夹里自带的post-commit文件,那是模板。

sudo vi /srv/svn/test/hooks/post-commit

在文件中添加如下内容:

#!/bin/sh
WEB=/var/www/html   #web服务器下的项目不能有空格。
#说明:post-commit会接受两个参数
REPOS="$1"  #/srv/svn/test  表示svn仓库的绝对路径值
REV="$2"  #表示最新的一个版本号。最后一个版本号
export LANG=en_US.UTF-8
svn update $WEB --username admin --password admin  #相当客户端的update操作
exit 0

如果不能判断自己写的shell脚本是否有错,可以现在hooks目录下运行./post-commit试一下

六. 配置https访问

1.安装OpenSSL

sudo apt-get install openssl

2.创建证书

sudo openssl req -x509 -newkey rsa:1024 -keyout apache.pem -out apache.pem -nodes -days 999

创建证书有两种方式:一种是自签名证书,一种是第三方CA机构签名证书。由于我们这里的证书只是保证传输数据安全性,因此我们使用自签名证书。

未分类

命令执行成功后会在当前目录生成一个apache.pem的证书,将这个文件复制到apache的配置目录/etc/apache2/ssl。

sudo mkdir /etc/apache2/ssl
sudo cp apache.pem /etc/apache2/ssl/

3.配置站点证书

sudo vi /etc/apache2/sites-available/default-ssl.conf
    SSLEngine on
    SSLCertificateFile    /etc/apache2/ssl/apache.pem
    #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

注意: SSLCertificateKeyFile前需要加#

如果配置没有问题,那么我们通过https协议就可以访问该IP地址了。

4.4配置apache服务器

/etc/apache2/mods-available/dav_svn.conf #加在文件最后面即可
<Location /svn >
DAV svn
#SVNPath /srv/svn/test
SVNParentPath /srv/svn
SVNListParentPath On
AuthType Basic
AuthName "welcome to subversion repository"
AuthUserFile /srv/svn/test/conf/passwd
AuthzSVNAccessFile /srv/svn/test/conf/authz
#<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
SSLRequireSSL #(https,否则取消)
#</LimitExcept>
</Location>

5.添加新用户或修改老用户密码

htpasswd -c /etc/subversion/passwd 用户名 //第一次设置用户时使用-c表示新建一个用户文件,之后取消-c.
回车后输入用户密码

6.重启Apache

sudo service apache2 restart

Centos 6.5搭建SVN服务器

鉴于在搭建时,参考网上很多资料,网上资料在有用的同时,也坑了很多人

本文的目的,也就是想让后继之人在搭建svn服务器时不再犯错,不再被网上漫天的坑爹作品所坑害,故此总结

/******开始*********/

系统环境:Centos 6.5

第一步:通过yum命令安装svnserve,命令如下:

>yum -y install subversion

此命令会全自动安装svn服务器相关服务和依赖,安装完成会自动停止命令运行

若需查看svn安装位置,可以用以下命令:

>rpm -ql subversion

第二步:创建版本库目录(此仅为目录,为后面创建版本库提供存放位置)

选择在var路径下创建版本库,当前处于根目录下,一次性创建如下:

>mkdir /var/svn/svnrepos

第三步:创建svn版本库

在第二步建立的路径基础上,创建版本库,命令如下:

>svnadmin create /var/svn/svnrepos/xxxx   (xxxx为你预期的版本库名称,可自定义)

创建成功后,进入xxx目录下

>cd /var/svn/svnrepos/xxxx

进入目录,可以看见如下文件信息:

未分类

第四步:配置修改

进入已经创建好的版本库目录下,也就是前文说创建的xxxx

进入conf

>cd /var/svn/svnrepos/xxxx/conf

conf目录下,一共存放三份重要的配置文件,如下:

未分类

  • authz:负责账号权限的管理,控制账号是否读写权限

  • passwd:负责账号和密码的用户名单管理

  • svnserve.conf:svn服务器配置文件

细节修改如下:(希望大家严格按照以下信息,不用参考网络上其他资料)

修改authz文件信息,如下:

>vi authz

在文件内容的末尾,添加如下:

未分类

只需在末尾添加,无需在文件其他部分修改和添加任何东西(请忽略groups被我马赛克的地方,那其实也是条无用的记录,我忘记删掉而已),末尾内容如下:

[]

账号1 = rw

账号2 = rw

。。。。。

rw表示赋予此账号可读写的权限,请注意[]中的斜杠,一定是反斜杠,有些教程说,需添加版本库名称在括号内,我直接建议就这写,这样写允许访问的权限更大,避免一些错误

修改passwd文件信息

>vi passwd

账号密码文件无需做修改,也是直接将账号和密码信息追加到文件中即可,注意格式为:

  • 账号 = 密码

  • 例如:admin = 123456

  • 修改svnserve.conf(重要)

  • vi svnserve.conf

原始文件内容,都被注释掉的,我们只需要去掉4条指定内容前注释即可,如下:

未分类

大多数网络资料,都会让大家将authz-db = authz这条给去掉注释,经过我本人多次被坑经验,此条去掉后,虽然svn服务器可以连接,但一直会提示“认证失败”,注释掉即可正常

还有多数资料会让大家在realm = My First Repository处填写服务器ip,经过测试,填写后并无什么用处,所以大家去掉注释即可,无需做任何修改

到此,配置已经全部完成,账号信息已经添加成功

第五步:防火墙开启

多数情况下服务器安装完成,配置完成后,无法连接svn服务器,均是防火墙问题,大家按照如下3条命令逐一执行即可

>/sbin/iptables -I INPUT -p tcp --dport 3690 -j ACCEPT

>/etc/init.d/iptables save

>service iptables restart

执行结果如下图:

未分类

六:启动svn服务器

在跟目录下,执行如下命令:

>svnserve -d -r /var/svn/svnrepos

启动成功后,可用ps -aux查看服务启动是否成功

七:客户端访问svn服务器

在windows客户端,输入地址:svn://ip地址:3690/xxxx (iP地址为你linux的ip,xxxx为前文创建的版本库名称,3690为svn默认端口)

弹出输入用户名和密码,输入即可访问

到此,Linux下svn服务器搭建就总结完毕,感谢大家的阅读。

git基本操作命令介绍

1、创建一个新的仓库:(选择一个合适的地方,创建一个空目录)

$mkdir learngit       //learngit是用git新建的一个目录
$cd learngit
$pwd       //pwd命令用于显示当前目录

2、 通过git init命令把这个目录编程git可以管理的仓库:

$git init

3、 用git add把文件添加到仓库: (可以一次add多个文件,可反复使用,添加多个文件,其实质是把文件添加到“工作区”的“暂存区”)

$git add **                 //**是文件名

4、 用git commit告诉git,把文件提交到仓库,其实质是把文件添加到“分支区”:

$git commit -m “**说明内容**”         //-m后面输入的是本次提交的说明        

5、$git status命令可以随时掌握工作区状态

$git status      //告诉你有文件被修改过
$git diff      //可以查看修改内容

6、 $git log 可以告诉我们历史记录,当前的仓库状态 (–pretty=oneline参数可以把历史记录整合到一行)

$git log                    //告诉我们历史记录

7、 HEAD表示当前的版本,上一版本就是HEAD^,上上一个版本就是HEAD^^,上100个版本就是HEAD~100

8、 $git reset –hard HEAD^ //退回到上一个版本,如果–hard 后面是跟commit id,就可回到该id所对应的状态

$git reset --hard HEAD^     

9、查看该文件的内容

$cat **             //**是文件名

10、 查看命令历史

$git reflog             //以便确定要回到未来的哪个版本

11、 撤销修改:

$git checkout -- **                //把**文件在工作区的修改全部撤销

①一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
②一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

12、 删除文件:

$rm **             //删除工作区的文件
$git rm             //删除工作区、暂存区的文件
$git commit             //删除分支的文件

13、 添加远程库:

$git remote add origin git@server-name:path/repo-name.git             //关联一个远程仓库
$git push -u origin master              //第一次推送master分支的所有内容
$git push origin master              //此后,每次本地提交后,只要有必要,使用此命令推送最新修改

14、 从远程库克隆:

$git clone ***           //***是远程仓库地址
$cd *filename*
$ls

15、 git中与分支相关:

$git branch             //查看分支
$git branch              //创建分支
$git checkout              //切换分支
$git checkout -b               //创建+切换分支
$git merge -b               //合并某分支到当前分支
$git branch -d              //删除分支
$git log --graph             //查看分支合并图
$git merge --no-ff -m "说明"               //可以用普通模式合并,合并后的历史有分支,能看出来曾经做过的合并,二fastforward合并看不出来曾经做过的合并

16、 多人协作:

1、首先,可以试图用git push origin branch-name推送自己的修改;
2、如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
3、如果合并有冲突,则解决冲突,并在本地提交;
4、没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
5、如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。

Git 分支管理与冲突解决

Git 分支提供了并行工作的功能。 假设你准备同时学习 git 和 SVN,你可以用两个分支分别来学习,完成之后进行合并,你就掌握了两种工具的使用了。 Git 和 GitHub 的基本操作可以参考我的这篇博客Git 和 GitHub 使用。

1. 分支管理

  • 查看分支 git brance

  • 创建分支 git branch dev # dev 是分支名

  • 切换分支 git checkout dev

  • 创建+切换 git checkout -b dev

未分类

  • 合并分支 git merge dev #分支 dev 合并到 master

  • 删除分支 git branch -d dev #已合并的分支

未分类

  • 强行删除分支 git branch -D dev #分支未合并
  • 查看分支图 git log –graph

未分类

远程仓库的分支

当你从远程仓库克隆时,实际上 Git 自动把本地的 master 分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。

未分类

如果要在远程仓库的其他分支 (如 dev 分支)上开发,就必须创建远程 origin/dev 分支到本地:

    git checkout -b dev origin/dev       #创建远程仓库的分支到本地,必须先克隆或关联一个远程分支

本地分支和远程分支的名字最好一致。

未分类

推送成功之后, GitHub 上的 MyRepos 仓库 dev 分支上增加了一个文件。

未分类

2. 分支合并模式

Fast forward 模式

默认模式,在这种模式下, 删除分支后,会丢掉分支信息,看不到合并记录.。并不是任何情况都能用这种模式。

普通模式

加上 --no-ff 参数就是普通模式。在普通模式下, Git 会在 merge 时生成一个新的 commit,这样从分支历史上就可以看出分支信息。

普通模式

未分类

快进模式

未分类

分支图

未分类

在分支图中, 红线是子分支 dev, 绿线是主分支 master. 子主分支分别提交了一次修改, 在将 dev 合并到 master 时发生冲突, 修改冲突文件内容之后再提交。

3. 解决冲突

如果两个分支都分别有了新的提交,Git 无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。必须手动解决冲突后再提交。git status 也可以告诉我们冲突的文件。

内容冲突

两个分支对同一文件的内容进行了修改并分别提交, 如果合并失败, 就必须手动解决冲突, 修改文件的内容之后再进行提交。

未分类

在冲突内容中, Git用<<<<<<>>>>>>标记出不同分支的内容. 文件的内容可以协商修改。

树冲突

一个分支修改了内容, 另个一分支删除了文件, 在试图合并时就会出现树冲突。假设子分支(如 dev)是要合并到主分支 master 的, 处理的方法有:

放弃 dev 的修改:强制删除 dev 分支, 然后提交即可。

放弃 master 的修改—-分下面两种情况:

  1. master 修改了内容, dev 删除了文件: 在 master 分支中删除该文件, 然后提交;
  2. master 删除了文件, dev 修改了内容: 在 master 分支中添加被修改的文件, 然后提交。

master 修改了内容, dev 删除了文件:

未分类

master 删除了文件, dev 修改了内容:

未分类

对于文件的移动(在 Git 仓库目录范围内)和重命名, Git 都可以自动合并。

远程仓库推送冲突

  • 从远程分支抓取最新的提交 git pull

  • 建立本地分支与远程分支的连接 git branch –set-upstream dev origin/dev # dev 为分支名

未分类

如果推送出现冲突, 先将远程分支最新的提交抓取下来, 在本地解决冲突之后再推送。解决冲突的方法与本地冲突完全相同

git代码merge和回滚操作

1. git merge

首先这里说说git merge操作

假如有以下的情况:
我本地和远程服务器各有一个代码仓库,本地的仓库有两个分支:master和dev分支,远程仓库也有两个分支:master和dev。两者一一对应。

假如我在dev分支上添加了很多的内容,并提交到了服务器,现在想在master分支上也加上同样的内容,怎么办呢?

方法有下面两种:

1.1 使用git merge命令

切换到master分支:git checkout master
合并分支:git merge dev

1.2 使用git cherry-pick命令

切换到master分支:git checkout master

git cherry-pick -n commit号 将某一次提交的内容合并过来
git cherry-pick ..dev 将dev分支的整个提交内容都合并过来
git cherry-pick dev

这里合并代码,难免会遇到冲突,对于webstorm用户,可以直接用自带的图形界面处理冲突,我这里推介visual studio code编辑器,微软良心作品。

2. git代码回滚

git代码库回滚: 指的是将代码库某分支退回到以前的某个commit id

2.1 本地代码库回滚

git reset --hard commit-id :回滚到commit-id,讲commit-id之后提交的commit都去除

git reset --hard HEAD~3:将最近3次的提交回滚

对于怎么看commit-id 可以使用命令:

未分类

结果如下:

未分类

画红圈的就是commit-id

2.2 远程代码库回滚

这个是重点要说的内容,过程比本地回滚要复杂

应用场景:自动部署系统发布后发现问题,需要回滚到某一个commit,再重新发布

原理:先将本地分支退回到某个commit,删除远程分支,再重新push本地分支

操作步骤:

1、git checkout master

2、git pull

3、git branch master_backup //备份一下这个分支当前的情况

4、git reset --hard the_commit_id //把master本地回滚到the_commit_id

5、git push origin :master //删除远程 master

6、git push origin master //用回滚后的本地分支重新建立远程分支

7、git branch -d master_backup //如果前面都成功了,删除这个备份分支

好,主要就这些了。