成长日志 2022-08-29T04:26:30+00:00 rayleignze@gmail.com 把 Home Assistant 接入到 Scratch 儿童编程中 2019-02-14T13:33:04+00:00 wiilz http://wiilz.cn/scratch 在家过了个年,把 Scratch 3.0 尚未成熟的插件体系搞明白了;一番倒腾之后把家里的 Home Assistant 桥接到了 Scratch 中,这样孩子也能在 Scratch 中编程控制到家里的智能设备了。编程中能接触真实世界中的东西,有助于激发孩子的兴趣。如图:

如果你也想试试,可以看看做好的脚本,已在 macOS 和 Debian 中测试可用,注意单步执行并检查结果:https://github.com/Yonsm/scratch-gui/blob/develop/scratch_setup.sh

由于 Scratch 3.0 插件机制还不完全成型,以上步骤中需要安装 node js,并自己运行修改的 scratch-gui 和 scratch-vm。为了孩子容易理解和易用,插件中我设定了固定的 Home Assistant 地址和长效令牌,需要自己修改(nano src/extensions/scratch3_homeassistant/index.js),运行后孩子可以直接选择设备以便执行相关操作,使用非常方便。

另外,如果孩子没有接触过 Scratch 编程,可以先用 http://code.org 做编程教育启蒙,家长和孩子均无需编程背景知识即可以入门,适合5岁+小朋友。

]]>
dash - 简单高效的 Home Assistant 操作面板 2019-01-02T11:01:04+00:00 wiilz http://wiilz.cn/dash dash.html 是为 Home Assistant 开发 Dashboard 操作面板,使用 HA WebSocket API 作为数据通道,基于非常简单的 HTML+JS+CSS 渲染而成的高效、快速的操控面板。

1. 用法

  • 使用方法非常简单,只要放入 www 目录,然后使用 http://xxx.xxx.xxx:8123/local/dash.html 访问即可。

    • 如果曾经登录过 Home Assistant 并保存过登录会话,访问 /local/dash.html 时会自动复用 HA localStorage accessToken 用于 WebSocket 认证。如果没有会提示转到 Home Assistant 主页登录,请选择保存本次登录才会记录 accessToken。
    • 最佳姿势:在 configuration.yaml 中加入以下配置,可以在侧栏中直接访问:
panel_iframe:
  dash:
    title: 面板
    icon: mdi:microsoft
    url: /local/dash.html
  • 指定地址:你也可以把 dash.html 放在任何位置,用浏览器打开后,在使用 dash.html?password@ws:host:8123 指定要访问的 WS API 地址,其中 password 可以是 HA Legacy Password 或者永久有效的 accessToken(在 HA 用户管理页面中创建“长期访问令牌”)。

  • 分组排序:dash.html 后面可以用#指定一个 group 名称(如 dash.html#group.dash,依此仅显示此分组的设备,且按这个分组排序(优先依据类型排序,同类型的按分组先后排序)。如果不指定,默认情况下使用 group.default_view 分组;如果不想使用分组,可以使用 dash.html#NA 来显示所有设备(如果你的 HA 中为使用分组功能,即 group.default_view 不存在,也会 fallback 到显示所有设备)。

2. 个性化配置

可以在 customize.yaml 中对特定的设备进行个性化定制,目前支持以下配置:

key 用途 不配置/默认情况 备注
dash_name 名称 使用 attributes.friendly_name 支持 template 模式
dash_icon 图标 传感器显示 state;空调显示当前温度;其它使用 attributes.icon 支持 template 模式
dash_extra 扩展信息 空调和风扇显示操作模式和设定温度,其它无 支持 template 模式
dash_extra_forced 强制显示扩展信息 off 状态下不显示扩展信息  
dash_click 点击时的动作 传感器无动作,其它执行开关操作 支持 http 链接或 JavaScript

关于 template 模式:支持以下几种示例:

  • 直接输入文字如,如 我的设备
  • 插入 state 宏,如 状态 ${sate}
  • 插入 attributes 宏,如 温度 ${temperature}℃
  • 插入其它设备的 state 宏,如 气温 ${sensor.caiyun_temperature}℃
  • 插入其它设备的 attributes 宏,如 气温 ${sensor.caiyun_weather.temperature}℃
  • 使用 JavaScript eval 运算,如eval:"${status}"=="Charging" ? "充电中" : "${status}"

更多个性化配置案例可以在我的 customize.yaml 中搜索 dash,以上几种用法基本上都能找到案例。

具体代码参考:https://github.com/Yonsm/HAExtra/blob/master/www/dash.html

]]>
espurna - 很棒的 Iot 设备/模块固件 2018-05-21T10:36:04+00:00 wiilz http://wiilz.cn/espurna espurna是一个非常高效、稳定的固件,支持Sonoff、NodeMCU和论坛的Hassmart 86模块(以及更多我没验证过的模块)。espurna很多配置是静态编译开关配置的,很适合批量产品(不像ESPEasy那样刷入后来动态配置),稳定性非常高,在Sonoff basic和Hassmart 86模块中运行20多天未重启(预期跑个半年没问题,哈哈)。

原作者代码主页:https://github.com/xoseperez/espurna 建议看看我修改过的配置:https://github.com/Yonsm/espurna/tree/Yonsm,具体修改了什么自己对比代码吧或者看git 记录吧…

另外,我为espurna增加了攀藤 PMS5003T/PMS5003ST 传感器的支持,完全重构替换了原作者PMS5003的代码,同时增加了自动休眠支持(否则一个传感器8000个小时/一年内就达到寿命极限了);同时添加了 Sense Air S8 CO2 传感器的支持。这些代码均已 PR 给原作者并已经合并到master主干。相关功能需自己通过编译配置来启用,或者NodeMCU可参考https://github.com/Yonsm/espurna/tree/Yonsm分支中的 nodemcu_lolin 配置。

原帖发布在:https://bbs.hassbian.com/thread-3814-1-1.html,贴中附件是我编译的部分Sonoff basic和Hassmart 86的固件,供不会编译的朋友使用。

]]>
Home Assistant 0.68 开始支持 HomeKit/Siri 了 2018-04-28T10:24:14+00:00 wiilz http://wiilz.cn/homekit Home Assistant 0.68 已经基本支持了绝大部分原来 HomeBridge 的能支持的组件,不用装node的HB,系统依赖大大减少,稳定性能系统消耗也小得多。现在理论上只要python3和libavahi-compat-libdnssd-dev就可以跑完整的HA和homekit功能了,路由器上运行HA应该不是问题了。

我PR了 binary_sensor、device_trackerCO2、light、PM2.5等传感器组件,已经包含在发布版本中了。另外 fan、media_player、vaccum 我当做switch先勉强用一下,需要的话可以参考我个人的HA版本:https://github.com/Yonsm/home-assistant/tree/Yonsm,后面会逐步支持完整的风扇、空气净化器组件,也会尝试PR到HA正式版本中。

HomeKit组件的文档在这:https://www.home-assistant.io/components/homekit/

其实配置很简单,configuration中加入一行 homekit: 可以了

树莓派,执行(装过HB的就不用这个了):sudo apt-get install libavahi-compat-libdnssd-dev 如果是非虚拟环境安装,提示加密错误,执行:pip3 install pycryptodome

]]>
ModBus 空调组件及中央空调接入 Home Assistant 简述 2018-04-28T10:09:04+00:00 wiilz http://wiilz.cn/modbus 写了个通用的 modbus.py 组件接入了HA,支持HomeKit/Siri,天猫精灵,简直是完美啊….

支持通用的ModBus协议的空调,包括走网络TCP的。另外新版HA里面有个modbus组件,写得实在不怎么样,也不具通用性。

Preview1

Preview2

Preview3

Preview4

1. 代码在此:

https://github.com/Yonsm/HAExtra/blob/master/custom_components/modbus2/climate.py

复制 homeassistant 的配置目录中 custom_components/climate/ 下,无此目录请创建。

2. 配置方法如下:

modbus:
  type: rtuovertcp
  host: 192.168.x.x
  port: 8899
 
climate:
  - platform: modbus2
    name: Daikin
    fan_mode: { registers: [6, 10, 14, 18] }
    fan_modes: { auto: 0, 一级: 1, 二级: 2, 三级: 3, 四级: 4, 五级: 5}
    hvac_mode: { registers: [5, 9, 13, 17] }
    hvac_modes: { 'off': 0, cool: 1, heat: 2, dry: 3, fan_only: 4 }
    hvac_off: { registers: [1, 2, 3, 4], register_type: coil }
    target_temperature: { registers: [4, 8, 12, 16] }
    temperature: { registers: [3, 6, 9, 12], register_type: input, scale: 0.1 }

上面是我自己的配置,完整的功能配置如下:

- platform: modbus2
  hub: ModBus,
  name: Daikin,
  
  fan_modes: { auto: 0, 一级: 1, 二级: 2, 三级: 3, 四级: 4, 五级: 5},
  hvac_modes: { 'off': 0, cool: 1, heat: 2, dry: 3, fan_only: 4 },
  preset_modes: { away: 0, home: 1 },
  swing_modes: { off: 0, both: 1, vertical: 2, horizontal: 3},
  aux_heat_off_value: 0,
  aux_heat_on_value: 1,
  aux_hvac_off_value: 0,
  aux_hvac_on_value: 1,

  aux_heat: { registers: [?, ?, ?] },
  fan_mode: { registers: [?, ?, ?] },
  humidity: { registers: [?, ?, ?] },
  hvac_mode: { registers: [?, ?, ?] },
  hvac_off: { registers: [?, ?, ?] },
  preset_mode: { registers: [?, ?, ?] },
  swing_mode: { registers: [?, ?, ?] },
  target_humidity: { registers: [?, ?, ?] },
  target_temperature: { registers: [?, ?, ?] },
  temperature: { registers: [?, ?, ?] },

其中 registers 是批量配置(即多个空调),当然也可以是单个的寄存,register: ?。完整的寄存器配置格式和 HomeAssistant ModBus Sensor 一致(除了我这里支持了批量 registers 之外):

  { registers: [3, 6, 9, 12], register_type: input|holding|coil, slave:1, scale: 0.1, data_type: float|int|uint|custom, count: 1, structure: '>i'}

3. 关于RTU模块

大金、美的、日立、海信等中央空调通用的方案,ModBus RTU模块980买的,再买了个485串口转WIFI的模块200,1180搞定了。ModBus RTU模块在X宝上找了唯一个一,980买的,…。485串口转WIFI买的是“有人”的,墙裂推荐,一看就是认真做事的公司的产品。网上没有现成的方案,过程中全部自己接线、调试,差点快被难度吓到放弃了——终于搞定了,简直是不可能完成的任务…

原帖发布在:https://bbs.hassbian.com/thread-3581-1-1.html

补充:最近看到一个接线视频,虽然不是一样的方案,但接线方法可以参考。

]]>
Saswell 地暖控制面板 - Home Assistant 插件 2018-04-11T12:31:09+00:00 wiilz http://wiilz.cn/saswell 从和Saswell官方app 的网关中拉取数据;过期了会自动拉取 token 无需操心和干预;比官方 app 使用和操作方便多了(官方 app 的日程操作很难用,不如直接在面板上设置);同时 HomeAssistant 启用 homekit 组件后支持在 Siri 中完美控制。

Preview

1. 代码在此:

https://github.com/Yonsm/HAExtra/blob/master/custom_components/climate/saswell.py

复制 homeassistant 的配置目录中 custom_components/climate/ 下,无此目录请创建。

2. 配置方法如下:

climate:
  - platform: saswell
    #name: Saswell
    username: ***@email.com
    password: ********
    #scan_interval: 300

自动列出账户下实际数量的设备,默认五分钟同步一次温度和状态(是不是慢了点儿,不过地暖本来就很慢:)

3. 关于Saswell 温控面板

型号为 SAS920WHL-7W-WIFI,价格368,X东和X猫均可购买(商家跟我没关系)。我自己家公共空间换用了 WIFI 版,卧室都是用199的无 WIFI 周编程版,型号SAS920WHL-7W,每天4-6个时间点定期自动切换,也够用了。

自行更换面板很容易,我原来是沃茨 W-H4111L(意格供暖js竟然不给有周编程功能的 W-H4111P ,不然就不用这么折腾了)

原帖发布在:https://bbs.hassbian.com/thread-3387-1-1.html

]]>
HAGenie - 天猫精灵一步接入 HomeAssistant 2018-02-06T09:13:15+00:00 wiilz http://wiilz.cn/hagenie 一、使用方法

天猫精灵后台配置流程,请参考这篇文章的步骤。直说能用的配置:

  • 账户授权连接:https://g.yonsm.net:8122/authorize.py
  • Client ID:hagenie(或者随便)
  • Client Secret:ga(随便输入即可)
  • Access Token URL:https://g.yonsm.net:8122/access.py
  • 开发者网关地址:https://g.yonsm.net:8122/gate.py
  • 设备管理跳转连接:(空)

以上配置后直接可以把天猫精灵和 HA 驳接起来了,在账户配置页面输入你的 HA UR http://xxx.xxx.xxx:8123 (注意:必须公网能访问的HA URL)和密码(关于密码的建议使用姿势参见最后)。

目前支持除 sensor 和其它设备的打开和关闭,能自动列出设备,基本零配置搞定全部事情,不需要搭建任何服务器。

二、进阶配置

天猫精灵最重要的三个参数:

  1. zone:仅支持特定的区域,如客厅、餐厅等,详细看这里
  2. deviceName:设备名称也只支持特定的,否则可以显示但它听不懂可能不能控制
  3. deviceType:必须从这个文档中候选

在 gate.py 中会尝试自动从 HA 的配置信息中,根据一些规则尝试自动识别。但有时候可能识别不了,可以在 customize.yaml 中为设备设定天猫精灵能认出来的区域和名称:

hagenie_zone: 客厅
hagenie_deviceName: 吸顶灯
hagenie_deviceType: outlet

以上 hagenie_zone 即可以在HA device entity设备中配置,也可以HA group entity下面给组内所有设备配置。

建议:把设备分组,分组名来自这里,设备名从这里选择 ,这样剩下的事情会自动搞定,不用配置。

三、自定义服务器

注意:以上配置理把所有密码发往我的服务器,虽然我肯定谨守不存、不看、不用三不政策(老社区信用口碑网友:),如果简单测试可以这么玩玩,如果要长期用建议自己搭建服务器,所有代码在这里,持续更新完善中:

https://github.com/Yonsm/HAExtra/tree/master/hagenie

  1. 服务器环境:其中三个 py 文件即可以在 apache 的 cgi-bin 下跑;也可以用 hagenie.py 作为服务器运行(需要完整的 server.pem,记住是需要 chain.pem cert.pem privkey.pem 合一,我被天猫精灵SSL检查这个坑了好久——如果看不明白,建议用前面的简单方式吧),hagenie.py可以在树莓派上跑,但响应比较慢会被天猫精灵服务器直接超时放弃,多试几次可能就好了,但控制起来了比较慢也不爽。

  2. Python 需求:以上支持 python2 或 python3,自动适应;如果 HA 是 https 的需要安装 requests,否则自动使用 urllib 或 urllib2。

  3. 实现细节:直接用 python 做了个伪 oauth2,并且把 oauth流程中流转的数据字段充分利用起来,用来传递 HA URL 地址和密码了…玩玩可以的,不要批评我的 “Oh … Alternative User Token Handover…to…”,哈哈

四、最佳姿势

如果你直接使用 hagenie.ga 服务器,推荐的姿势是使用密码(以便自己访问),但在天猫精灵开发者控制台中不要输入正确的密码(这样不会被 hagenie 服务器看到明文密码了),但在 configuration.yaml 中加入以下配置来信任 hagenie.ga 服务器的 IP 地址:

http:
  api_password: *****
  trusted_networks:
    - 127.0.0.1
    - 101.132.66.191
    - 192.168.1.0/24

原帖发布在:https://bbs.hassbian.com/thread-2700-1-1.html

]]>
斐讯悟空 M1 传感器 - Home Assistant 插件 2018-02-05T05:05:51+00:00 wiilz http://wiilz.cn/phicomm 模拟斐讯的手机 app,从斐讯官方拉取数据;过期了会自动拉取 token 无需操心和干预;也不会和官方的“斐讯空能净” 互斥登录踢出。

Preview

1. 代码在此:

https://github.com/Yonsm/HAExtra/blob/master/custom_components/sensor/phicomm.py

复制 homeassistant 的配置目录中 custom_components/sensor/ 下,无此目录请创建。

2. 配置方法如下:

sensor:
  - platform: phicomm
    #name: Phicomm
    username: 139********
    password: ********
    #scan_interval: 120
    #sensors: [pm25,hcho,temperature,humidity]

自动列出账户下的多个斐讯悟空设备;启用了四个传感器类型;每60秒更新一次;每个传感器均仔细挑选了 mdi 的图标,无需额外配置。

3. 【可选】上面配置好了之后就可以了,但默认是英文名称。建议 customize.yaml 中配置中文名称如下:

sensor.aircat_temperature:
  friendly_name: 温度
sensor.aircat_humidity:
  friendly_name: 湿度
sensor.aircat_pm25:
  friendly_name: 颗粒物
  homebridge_name: 空气质量
sensor.aircat_hcho:
  friendly_name: 甲醛

4. 【可选】建议在 groups.yaml 中添加如下代码进行分组:

xxxx_room:
    entities:
      - sensor.phicomm_temperature
      - sensor.phicomm_humidity
      - sensor.phicomm_pm25
      - sensor.phicomm_hcho

原帖发布在:https://bbs.hassbian.com/thread-2698-1-1.html

]]>
彩云天气传感器 - Home Assistant 插件 2018-02-04T04:48:25+00:00 wiilz http://wiilz.cn/caiyun 对标 HA 内置 yr 天气插件的高质量 HA custom_component。

Preview

1. 代码在此:

https://github.com/Yonsm/HAExtra/blob/master/custom_components/sensor/caiyun.py

复制 homeassistant 的配置目录中 custom_components/sensor/ 下,无此目录请创建。

2. 配置方法和 yr 类似,最简单的配置版本如下:

sensor:
  - platform: caiyun

以上默认启用这些传感器20分钟更新一次,自动使用 HA 中配置的地理位置。

下面是完整的配置项,每个传感器均仔细挑选了 mdi 的图标,无需额外配置:

sensor:
  - platform: caiyun
    #name: CaiYun
    #scan_interval: 1200
    #latitude: 30.000
    #longitude: 120.000
    monitored_conditions: # Optional
      - weather
      - temperature
      - humidity
      - cloud_rate
      - pressure
      - wind_direction
      - wind_speed
      - local_precipitation
      - nearest_precipitation
      - precipitation_distance
      - aqi
      - pm25
      - pm10
      - o3
      - co
      - no2
      - so2

3. 【可选】上面配置好了之后就可以了,但默认是英文名称。建议 customize.yaml 中配置中文名称如下:

group.outside:
  friendly_name: 室外
sun.sun:
  friendly_name: 日照

sensor.caiyun_weather:
  friendly_name: 天气
sensor.caiyun_temperature:
  friendly_name: 室外气温
sensor.caiyun_humidity:
  friendly_name: 室外湿度
sensor.caiyun_cloud_rate:
  friendly_name: 云量
sensor.caiyun_pressure:
  friendly_name: 气压
sensor.caiyun_wind_direction:
  friendly_name: 风向
sensor.caiyun_wind_speed:
  friendly_name: 风速
sensor.caiyun_local_precipitation:
  friendly_name: 降水强度
sensor.caiyun_nearest_precipitation:
  friendly_name: 附近降水强度
sensor.caiyun_precipitation_distance:
  friendly_name: 附近降水距离
sensor.caiyun_aqi:
  friendly_name: 空气指数
sensor.caiyun_pm25:
  friendly_name: 室外颗粒物
  homebridge_name: 空气质量
sensor.caiyun_pm10:
  friendly_name: 室外大颗粒物
sensor.caiyun_o3:
  friendly_name: 室外臭氧
sensor.caiyun_co:
  friendly_name: 室外一氧化碳
sensor.caiyun_no2:
  friendly_name: 室外二氧化氮
sensor.caiyun_so2:
  friendly_name: 室外二氧化硫

4. 【可选】建议在 groups.yaml 中添加如下代码进行分组:

outside:
    entities:
      - sun.sun
      - sensor.caiyun_weather
      - sensor.caiyun_temperature
      - sensor.caiyun_humidity
      - sensor.caiyun_cloud_rate
      - sensor.caiyun_pressure
      - sensor.caiyun_wind_direction
      - sensor.caiyun_wind_speed
      - sensor.caiyun_local_precipitation
      - sensor.caiyun_nearest_precipitation
      - sensor.caiyun_precipitation_distance
      - sensor.caiyun_aqi
      - sensor.caiyun_pm25
      - sensor.caiyun_pm10
      - sensor.caiyun_o3
      - sensor.caiyun_co
      - sensor.caiyun_no2
      - sensor.caiyun_so2

原帖发布在:https://bbs.hassbian.com/thread-2697-1-1.html

]]>
git笔记 2017-07-31T13:00:12+00:00 wiilz http://wiilz.cn/git-note 常用Git命令

原文参考自:廖雪峰的git教程

创建git仓库

1.创建版本库,在合适的位置创建空目录;

$ mkdir learngit  (创建文件夹“learngit”)
$ cd learngit
$ pwd  (查看路径)
/Users/michael/learngit

2.git init初始化Git可以管理的仓库:

$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/

ls -ah查看所有文件(包括隐藏)

将文件提交到Git仓库

第一步,编写一个新文件read.txt,用git add <file>将其放到git仓库暂存区中

 $ git add readme.txt 

第二步,用git commit把文件提交到仓库:

$ git commit -m "wrote a readme file"
[master (root-commit) cb926e7] wrote a readme file
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

小结

初始化一个Git仓库,使用git init命令。

添加文件到Git仓库,分两步:

  • 第一步,使用命令git add ,注意,可反复多次使用,添加多个文件;

  • 第二步,使用命令git commit -m “xxx-message”,完成。


查看工作区状态

要随时掌握工作区的状态,使用git status命令。

如果git status告诉你有文件被修改过

用git diff可以查看修改内容

使用git log查看历史提交记录,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数:

$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file

版本回退

在Git中,用HEAD 表示当前版本,指向最新的comment id,上一个版本就是 HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

退回上一个版本

$ git reset --hard HEAD^

或者直接使用版本号

$ git reset --hard 3628164  (comment id前几位即可)
HEAD is now at 3628164 append GPL

回退版本后又想撤销恢复,需要知道恢复版本的id,这里可以用git reflog查看命令历史以确定comment id。

$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file

小结

HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

git log可以查看提交历史,以便确定要回退到哪个版本。

git reflog查看命令历史,以便确定要回到未来的哪个版本。


管理修改

工作区和暂存区

git add <file> 实际上就是把文件修改添加到暂存区;

git comment -m "xxx-message" 实际上就是把暂存区的所有内容提交到当前分支。

提交后可以用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:

每次修改,如果不add到暂存区,那就不会加入到commit中。

撤销修改

git checkout -- <file>可以丢弃工作区的修改:

$ git checkout -- readme.txt

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。

如果已经git add 到暂存区了,可以使用命令 git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区。

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。

小结

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout -- file

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。

删除文件

一种情况是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:

$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d17efd8] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

现在,文件就从版本库中被删除了。

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:


$ git checkout -- test.txt

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

小结

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。

添加远程库

在github上新建仓库,使本地库与之关联

$ git remote add origin git@github.com:michaelliao/learngit.git

git push命令,实际上是把本地当前分支master推送到远程

$ git push -u origin master

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

$ git push origin master

小结

要关联一个远程库,使用命令 git remote add origin git@server-name:path/repo-name.git

关联后,使用命令 git push -u origin master 第一次推送 master 分支的所有内容;

此后,每次本地提交后,只要有必要,就可以使用命令 git push origin master 推送最新修改;

从远程库克隆

要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。

$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

$ cd gitskills
$ ls
README.md

Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。

创建与合并分支

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>

解决冲突

如果不同分支同时修改了相同文件,在一起提交git merge 合并分支时会发生冲突

$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

我们可以直接查看readme.txt的内容:

Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改后再提交:

用带参数的git log也可以看到分支的合并情况:

$ git log --graph --pretty=oneline --abbrev-commit
*   59bc1cb conflict fixed
|\
| * 75a857c AND simple
* | 400b400 & simple
|/
* fec145a branch test
...

小结

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

git log --graph命令可以看到分支合并图。

分支管理

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

可以试一下--no-ff方式的git merge

准备备合并dev分支,请注意--no-ff参数,表示禁用Fast forward

$ git merge --no-ff -m "merge with no-ff" dev
 Merge made by the 'recursive' strategy.
 readme.txt |    1 +
 1 file changed, 1 insertion(+)

因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

合并后,我们用git log看看分支历史:

$ git log --graph --pretty=oneline --abbrev-commit
*   7825a50 merge with no-ff
|\
| * 6224937 add merge
|/
*   59bc1cb conflict fixed
...

可以看到,不使用Fast forward模式,merge后就像这样:

git-no-ff-mode

Bug/Feature分支

当前正在dev上进行的工作还没有提交,现在需要创建一个分支issue-101来修复bug


```shell
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge

修复完bug后切回dev分支

$ git checkout dev
Switched to branch 'dev'
$ git status
# On branch dev
nothing to commit (working directory clean)

工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:

$ git stash list
stash@{0}: WIP on dev: 6224937 add merge

工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

另一种方式是用git stash pop,恢复的同时把stash内容也删了:

$ git stash pop
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   readme.txt
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)

再用git stash list查看,就看不到任何stash内容了:

$ git stash list

你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

$ git stash apply stash@{0}

小结

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

开发一个新feature,最好新建一个分支;

如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

多人协作

多人协作的工作模式通常是这样:

首先,可以试图用git push origin branch-name推送自己的修改;

如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

如果合并有冲突,则解决冲突,并在本地提交;

没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!

如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

小结

查看远程库信息,使用git remote -v

本地新建的分支如果不推送到远程,对其他人就是不可见的;

从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;

在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;

建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name

从远程抓取分支,使用git pull`,如果有冲突,要先处理冲突。

标签管理

  • 命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id
$ git tag v0.9 6224937
  • git tag -a <tagname> -m "blablabla..." 可以指定标签信息;
$ git tag -a v0.1 -m "version 0.1 released" 3628164
  • git tag -s <tagname> -m "blablabla..." 可以用PGP签名标签;

  • 命令git tag可以查看所有标签。

  • git show <tagname>查看标签信息:

$ git show v0.9
commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
Author: Michael Liao <askxuefeng@gmail.com>
Date:   Thu Aug 22 11:22:08 2013 +0800

    add merge
...
  • 命令git push origin <tagname>可以推送一个本地标签;或者,一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 554 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
 * [new tag]         v0.2 -> v0.2
 * [new tag]         v0.9 -> v0.9
  • 命令git push origin --tags可以推送全部未推送过的本地标签;

  • 命令git tag -d <tagname>可以删除一个本地标签;

$ git tag -d v0.9
Deleted tag 'v0.9' (was 6224937)
  • 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。
$ git push origin :refs/tags/v0.9
To git@github.com:michaelliao/learngit.git
 - [deleted]         v0.9

自定义Git

  • 忽略某些文件时,需要编写.gitignore.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!

GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:

https://github.com/github/gitignore

  • 如果你确实想添加某已忽略文件,可以用-f强制添加到Git:
$ git add -f App.class
  • 如果你发现可能.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
$ git check-ignore -v App.class
.gitignore:3:*.class    App.class

Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。

]]>