From 3b9fe6c680bb659c5780516ada2bf1b7bc8cd126 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 20 Feb 2022 17:54:47 +0800 Subject: [PATCH 01/10] new branch --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b9a73e --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# new branch From d88ac7354abf217ef3a6ce8485ab05a83fc603fa Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 20 Feb 2022 22:20:22 +0800 Subject: [PATCH 02/10] initialize docsify --- README.md | 1 - docs/.nojekyll | 0 docs/README.md | 3 +++ docs/index.html | 22 ++++++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) delete mode 100644 README.md create mode 100644 docs/.nojekyll create mode 100644 docs/README.md create mode 100644 docs/index.html diff --git a/README.md b/README.md deleted file mode 100644 index 7b9a73e..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# new branch diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2f86d57 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +# 首页 + +> An awesome project. diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..4378236 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,22 @@ + + + + + GitHub 漫游指南 + + + + + + +
内容加载中
+ + + + + From 550fb2161eb1e3297d38467b947b811ed8eda518 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 21 Feb 2022 10:27:59 +0800 Subject: [PATCH 03/10] apply docsify - sidebar --- README.md | 177 + docs/README.md | 14 +- docs/_sidebar.md | 3 + docs/chapter/Github漫游指南.md | 4003 +++++++++++++++++ docs/chapter/_sidebar.md | 0 docs/chapter/img/10000.png | Bin 0 -> 102288 bytes docs/chapter/img/2014-01-01.png | Bin 0 -> 37125 bytes docs/chapter/img/2014.png | Bin 0 -> 97151 bytes docs/chapter/img/2015.png | Bin 0 -> 95654 bytes docs/chapter/img/2016.png | Bin 0 -> 96599 bytes docs/chapter/img/365-streak.jpg | Bin 0 -> 64424 bytes docs/chapter/img/after-add.png | Bin 0 -> 105736 bytes docs/chapter/img/alipay.png | Bin 0 -> 4484 bytes docs/chapter/img/api-examples.png | Bin 0 -> 136795 bytes docs/chapter/img/before-add.png | Bin 0 -> 122940 bytes docs/chapter/img/clone-flask.png | Bin 0 -> 66877 bytes docs/chapter/img/comparison.png | Bin 0 -> 268659 bytes docs/chapter/img/cover.jpg | Bin 0 -> 45069 bytes docs/chapter/img/echoesworks.png | Bin 0 -> 18114 bytes docs/chapter/img/eclipse-cla.png | Bin 0 -> 90080 bytes docs/chapter/img/elasticsearch_ionit_map.jpg | Bin 0 -> 64040 bytes docs/chapter/img/favicon.ico | Bin 0 -> 6518 bytes docs/chapter/img/feb-results.png | Bin 0 -> 41353 bytes docs/chapter/img/feel-free-to.png | Bin 0 -> 197947 bytes docs/chapter/img/flask-0.1.png | Bin 0 -> 486984 bytes docs/chapter/img/flask-init.png | Bin 0 -> 550196 bytes docs/chapter/img/flask.png | Bin 0 -> 192098 bytes docs/chapter/img/for-stars-make-money.png | Bin 0 -> 314248 bytes docs/chapter/img/for-stars.png | Bin 0 -> 142505 bytes docs/chapter/img/git-diff-screenshot.png | Bin 0 -> 294158 bytes docs/chapter/img/github-200-days.png | Bin 0 -> 234200 bytes docs/chapter/img/github-365.jpg | Bin 0 -> 123028 bytes docs/chapter/img/github-500.jpg | Bin 0 -> 127591 bytes docs/chapter/img/github-desktop.jpg | Bin 0 -> 171139 bytes docs/chapter/img/github-intro.png | Bin 0 -> 90058 bytes .../img/github-new-project-checklist.png | Bin 0 -> 143833 bytes docs/chapter/img/github-no-open.jpg | Bin 0 -> 219914 bytes docs/chapter/img/github-roam-create.jpg | Bin 0 -> 60840 bytes docs/chapter/img/github-star-history.png | Bin 0 -> 38647 bytes docs/chapter/img/github-trending-example.png | Bin 0 -> 279827 bytes docs/chapter/img/github_traffic.png | Bin 0 -> 133315 bytes docs/chapter/img/go-mqtt.png | Bin 0 -> 88272 bytes docs/chapter/img/google-cla.png | Bin 0 -> 50161 bytes .../img/google-new-project-checklist.png | Bin 0 -> 67456 bytes docs/chapter/img/gource.jpg | Bin 0 -> 66799 bytes docs/chapter/img/growth-ebook-example.png | Bin 0 -> 205686 bytes docs/chapter/img/growth.png | Bin 0 -> 221811 bytes docs/chapter/img/growth_traffic.png | Bin 0 -> 242941 bytes docs/chapter/img/grwoth-old.png | Bin 0 -> 161544 bytes docs/chapter/img/huovd.png | Bin 0 -> 16242 bytes docs/chapter/img/it-works-cms.png | Bin 0 -> 154254 bytes docs/chapter/img/lan-example.png | Bin 0 -> 156344 bytes docs/chapter/img/lan-iot.jpg | Bin 0 -> 67115 bytes docs/chapter/img/lan.png | Bin 0 -> 14287 bytes docs/chapter/img/lettuce.png | Bin 0 -> 164780 bytes docs/chapter/img/licenses.png | Bin 0 -> 279836 bytes docs/chapter/img/linux-history.png | Bin 0 -> 344949 bytes docs/chapter/img/lodash-code-example.png | Bin 0 -> 299472 bytes docs/chapter/img/longest-streak.png | Bin 0 -> 105612 bytes docs/chapter/img/main-events.png | Bin 0 -> 18949 bytes docs/chapter/img/mole.png | Bin 0 -> 168600 bytes docs/chapter/img/mopass-weibo.png | Bin 0 -> 210621 bytes docs/chapter/img/nginx_pig.jpg | Bin 0 -> 29497 bytes .../img/permissive-vs-copylift-license-2.jpg | Bin 0 -> 72994 bytes docs/chapter/img/phodal-intro.jpg | Bin 0 -> 88103 bytes docs/chapter/img/phodal-results.png | Bin 0 -> 8798 bytes docs/chapter/img/problem.jpg | Bin 0 -> 44212 bytes docs/chapter/img/project-init.jpg | Bin 0 -> 130528 bytes docs/chapter/img/pycharm-diff.jpg | Bin 0 -> 320141 bytes .../img/python-social-auth-example.png | Bin 0 -> 339773 bytes docs/chapter/img/qingxu.jpg | Bin 0 -> 98188 bytes docs/chapter/img/qrcode.jpg | Bin 0 -> 25799 bytes docs/chapter/img/react-features-example.png | Bin 0 -> 277566 bytes docs/chapter/img/react-intro.png | Bin 0 -> 210736 bytes docs/chapter/img/readme-example.png | Bin 0 -> 239274 bytes docs/chapter/img/redux-examples.png | Bin 0 -> 324123 bytes docs/chapter/img/replace.jpg | Bin 0 -> 54130 bytes docs/chapter/img/repo-status.png | Bin 0 -> 25761 bytes docs/chapter/img/resume.png | Bin 0 -> 204968 bytes docs/chapter/img/rpc-example.png | Bin 0 -> 201336 bytes docs/chapter/img/sherlock.png | Bin 0 -> 131592 bytes docs/chapter/img/skillmap.png | Bin 0 -> 119631 bytes docs/chapter/img/skilltree.jpg | Bin 0 -> 105008 bytes docs/chapter/img/smtwtfs.png | Bin 0 -> 8528 bytes docs/chapter/img/solr.png | Bin 0 -> 248743 bytes docs/chapter/img/sourcetree.jpg | Bin 0 -> 184898 bytes docs/chapter/img/wechat-pay.png | Bin 0 -> 54943 bytes docs/chapter/img/wechat.jpg | Bin 0 -> 21121 bytes docs/chapter/img/xiaomiquan.jpg | Bin 0 -> 10746 bytes docs/index.html | 17 +- phodal.ico | Bin 0 -> 13032 bytes 91 files changed, 4209 insertions(+), 5 deletions(-) create mode 100644 README.md create mode 100644 docs/_sidebar.md create mode 100644 docs/chapter/Github漫游指南.md create mode 100644 docs/chapter/_sidebar.md create mode 100644 docs/chapter/img/10000.png create mode 100644 docs/chapter/img/2014-01-01.png create mode 100644 docs/chapter/img/2014.png create mode 100644 docs/chapter/img/2015.png create mode 100644 docs/chapter/img/2016.png create mode 100644 docs/chapter/img/365-streak.jpg create mode 100644 docs/chapter/img/after-add.png create mode 100644 docs/chapter/img/alipay.png create mode 100644 docs/chapter/img/api-examples.png create mode 100644 docs/chapter/img/before-add.png create mode 100644 docs/chapter/img/clone-flask.png create mode 100644 docs/chapter/img/comparison.png create mode 100644 docs/chapter/img/cover.jpg create mode 100644 docs/chapter/img/echoesworks.png create mode 100644 docs/chapter/img/eclipse-cla.png create mode 100644 docs/chapter/img/elasticsearch_ionit_map.jpg create mode 100644 docs/chapter/img/favicon.ico create mode 100644 docs/chapter/img/feb-results.png create mode 100644 docs/chapter/img/feel-free-to.png create mode 100644 docs/chapter/img/flask-0.1.png create mode 100644 docs/chapter/img/flask-init.png create mode 100644 docs/chapter/img/flask.png create mode 100644 docs/chapter/img/for-stars-make-money.png create mode 100644 docs/chapter/img/for-stars.png create mode 100644 docs/chapter/img/git-diff-screenshot.png create mode 100644 docs/chapter/img/github-200-days.png create mode 100644 docs/chapter/img/github-365.jpg create mode 100644 docs/chapter/img/github-500.jpg create mode 100644 docs/chapter/img/github-desktop.jpg create mode 100644 docs/chapter/img/github-intro.png create mode 100644 docs/chapter/img/github-new-project-checklist.png create mode 100644 docs/chapter/img/github-no-open.jpg create mode 100644 docs/chapter/img/github-roam-create.jpg create mode 100644 docs/chapter/img/github-star-history.png create mode 100644 docs/chapter/img/github-trending-example.png create mode 100644 docs/chapter/img/github_traffic.png create mode 100644 docs/chapter/img/go-mqtt.png create mode 100644 docs/chapter/img/google-cla.png create mode 100644 docs/chapter/img/google-new-project-checklist.png create mode 100644 docs/chapter/img/gource.jpg create mode 100644 docs/chapter/img/growth-ebook-example.png create mode 100644 docs/chapter/img/growth.png create mode 100644 docs/chapter/img/growth_traffic.png create mode 100644 docs/chapter/img/grwoth-old.png create mode 100644 docs/chapter/img/huovd.png create mode 100644 docs/chapter/img/it-works-cms.png create mode 100644 docs/chapter/img/lan-example.png create mode 100644 docs/chapter/img/lan-iot.jpg create mode 100644 docs/chapter/img/lan.png create mode 100644 docs/chapter/img/lettuce.png create mode 100644 docs/chapter/img/licenses.png create mode 100644 docs/chapter/img/linux-history.png create mode 100644 docs/chapter/img/lodash-code-example.png create mode 100644 docs/chapter/img/longest-streak.png create mode 100644 docs/chapter/img/main-events.png create mode 100644 docs/chapter/img/mole.png create mode 100644 docs/chapter/img/mopass-weibo.png create mode 100644 docs/chapter/img/nginx_pig.jpg create mode 100644 docs/chapter/img/permissive-vs-copylift-license-2.jpg create mode 100644 docs/chapter/img/phodal-intro.jpg create mode 100644 docs/chapter/img/phodal-results.png create mode 100644 docs/chapter/img/problem.jpg create mode 100644 docs/chapter/img/project-init.jpg create mode 100644 docs/chapter/img/pycharm-diff.jpg create mode 100644 docs/chapter/img/python-social-auth-example.png create mode 100644 docs/chapter/img/qingxu.jpg create mode 100644 docs/chapter/img/qrcode.jpg create mode 100644 docs/chapter/img/react-features-example.png create mode 100644 docs/chapter/img/react-intro.png create mode 100644 docs/chapter/img/readme-example.png create mode 100644 docs/chapter/img/redux-examples.png create mode 100644 docs/chapter/img/replace.jpg create mode 100644 docs/chapter/img/repo-status.png create mode 100644 docs/chapter/img/resume.png create mode 100644 docs/chapter/img/rpc-example.png create mode 100644 docs/chapter/img/sherlock.png create mode 100644 docs/chapter/img/skillmap.png create mode 100644 docs/chapter/img/skilltree.jpg create mode 100644 docs/chapter/img/smtwtfs.png create mode 100644 docs/chapter/img/solr.png create mode 100644 docs/chapter/img/sourcetree.jpg create mode 100644 docs/chapter/img/wechat-pay.png create mode 100644 docs/chapter/img/wechat.jpg create mode 100644 docs/chapter/img/xiaomiquan.jpg create mode 100644 phodal.ico diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d266ae --- /dev/null +++ b/README.md @@ -0,0 +1,177 @@ +# GitHub 漫游指南 + +> 漫游,即随意游玩~。 + +在线阅读:[GitHub 漫游指南](http://github.phodal.com/),下载:[pdf](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.pdf)、[mobi](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.mobi)、[epub](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.epub) + +2014 年,写了《[一步步搭建物联网系统](https://github.com/phodal/designiot)》(电子书)。 + +2015.3.9 号,想着写个《[GitHub 漫游指南](http://github.phodal.com/)》,于是在最开始的地方写着: + +> 我的 GitHub 主页上写着加入的时间——``Joined on Nov 8, 2010``,那时才大一。在那之后的日子里,也许是因为我学的不是计算机的关系,并没有熟练使用它。到了今天——``2015.3.9``,我发现 GitHub 是程序员的社交网站。 + +但是过了很久都没有动静,今天是 2015.10.24,我想是时候完成这个目标了。 + +## 目录 + +* [前言](http://github.phodal.com/#前言) + * [我与 GitHub 的故事](http://github.phodal.com/#我与github的故事) + * [GitHub 与收获](http://github.phodal.com/#github与收获) + * [GitHub 与成长](http://github.phodal.com/#github与成长) + * [为什么你应该深入 GitHub](http://github.phodal.com/#为什么你应该深入github) + * [方便工作](http://github.phodal.com/#方便工作) + * [获得一份工作](http://github.phodal.com/#获得一份工作) + * [扩大交际](http://github.phodal.com/#扩大交际) +* [创建开源项目](http://github.phodal.com/#创建开源项目) + * [取一个好的名字](http://github.phodal.com/#取一个好的名字) + * [挑选好 LICENSE](http://github.phodal.com/#挑选好-license) + * [官方主页](http://github.phodal.com/#官方主页) +* [Git 基本知识与 GitHub 使用](http://github.phodal.com/#git基本知识与github使用) + * [Git](http://github.phodal.com/#git) + * [Git初入](http://github.phodal.com/#git初入) + * [GitHub](http://github.phodal.com/#github) + * [版本管理与软件部署](http://github.phodal.com/#版本管理与软件部署) + * [GitHub与Git](http://github.phodal.com/#github与git) + * [在GitHub创建项目](http://github.phodal.com/#在github创建项目) + * [GitHub 流行项目分析](http://github.phodal.com/#github流行项目分析) + * [Pull Request](http://github.phodal.com/#pull-request) + * [我的第一个PR](http://github.phodal.com/#我的第一个pr) + * [CLA](http://github.phodal.com/#cla) +* [构建 GitHub 项目](http://github.phodal.com/#构建github项目) + * [如何用好 GitHub](http://github.phodal.com/#如何用好github) + * [敏捷软件开发](http://github.phodal.com/#敏捷软件开发) + * [测试](http://github.phodal.com/#测试) + * [CI](http://github.phodal.com/#ci) + * [代码质量](http://github.phodal.com/#代码质量) + * [模块分离与测试](http://github.phodal.com/#模块分离与测试) + * [代码模块化](http://github.phodal.com/#代码模块化) + * [自动化测试](http://github.phodal.com/#自动化测试) + * [Jshint](http://github.phodal.com/#jshint) + * [Mocha](http://github.phodal.com/#mocha) + * [测试示例](http://github.phodal.com/#测试示例) + * [代码质量与重构](http://github.phodal.com/#代码质量与重构) + * [Code Climate](http://github.phodal.com/#code-climate) + * [代码的坏味道](http://github.phodal.com/#代码的坏味道) +* [Git 提交信息及几种不同的规范](http://github.phodal.com/#git-提交信息及几种不同的规范) + * [工作写法](http://github.phodal.com/#工作写法) + * [常规写法](http://github.phodal.com/#常规写法) + * [开源应用、开源库写法](http://github.phodal.com/#开源应用开源库写法) +* [创建项目文档](http://github.phodal.com/#创建项目文档) + * [README](http://github.phodal.com/#readme) + * [在线文档](http://github.phodal.com/#在线文档) + * [可用示例](http://github.phodal.com/#可用示例) +* [改善 GitHub 项目代码质量:重构](http://github.phodal.com/#改善-github-项目代码质量重构) + * [为什么重构?](http://github.phodal.com/#为什么重构) + * [重构 uMarkdown](http://github.phodal.com/#重构umarkdown) + * [代码说明](http://github.phodal.com/#代码说明) + * [Intellij Idea 重构](http://github.phodal.com/#intellij-idea重构) + * [Rename](http://github.phodal.com/#rename) + * [Extract Method](http://github.phodal.com/#extract-method) + * [Inline Method](http://github.phodal.com/#inline-method) + * [Pull Members Up](http://github.phodal.com/#pull-members-up) + * [重构之以查询取代临时变量](http://github.phodal.com/#重构之以查询取代临时变量) +* [改善 GitHub 项目代码质量:测试](http://github.phodal.com/#改善-github-项目代码质量测试) + * [TDD](http://github.phodal.com/#tdd) + * [一次测试驱动开发](http://github.phodal.com/#一次测试驱动开发) + * [说说TDD](http://github.phodal.com/#说说tdd) + * [TDD思考](http://github.phodal.com/#tdd思考) + * [功能测试](http://github.phodal.com/#功能测试) + * [轻量级网站测试TWill](http://github.phodal.com/#轻量级网站测试twill) + * [Twill 登陆测试](http://github.phodal.com/#twill-登陆测试) + * [Twill 测试脚本](http://github.phodal.com/#twill-测试脚本) + * [Fake Server](http://github.phodal.com/#fake-server) +* [如何推广](http://github.phodal.com/#如何推广) + * [Marketing First](http://github.phodal.com/#marketing-first) + * [编写一个好的 README](http://github.phodal.com/#编写一个好的-readme) + * [这个项目做什么——一句话文案](http://github.phodal.com/#这个项目做什么一句话文案) + * [它解决了什么问题](http://github.phodal.com/#它解决了什么问题) + * [它有什么特性](http://github.phodal.com/#它有什么特性) + * [安装及 hello,world 示例](http://github.phodal.com/#安装及hello-world-示例) + * [技术文档](http://github.phodal.com/#技术文档) + * [技术文档](http://github.phodal.com/#技术文档-1) + * [更多的示例程序](http://github.phodal.com/#更多的示例程序) + * [编写技术文章、书籍](http://github.phodal.com/#编写技术文章书籍) + * [鼓励、吸引贡献者](http://github.phodal.com/#鼓励吸引贡献者) +* [开源项目维护](http://github.phodal.com/#开源项目维护) + * [Release](http://github.phodal.com/#release) +* [Git 工具推荐](http://github.phodal.com/#git-工具推荐) +* [GitHub 用户分析](http://github.phodal.com/#github用户分析) + * [生成图表](http://github.phodal.com/#生成图表) + * [数据解析](http://github.phodal.com/#数据解析) + * [Matplotlib](http://github.phodal.com/#matplotlib) + * [每周分析](http://github.phodal.com/#每周分析) + * [Python GitHub 每周情况分析](http://github.phodal.com/#python-github-每周情况分析) + * [Python 数据分析](http://github.phodal.com/#python-数据分析) + * [Python Matplotlib 图表](http://github.phodal.com/#python-matplotlib图表) + * [存储到数据库中](http://github.phodal.com/#存储到数据库中) + * [SQLite3](http://github.phodal.com/#sqlite3) + * [数据导入](http://github.phodal.com/#数据导入) + * [Redis](http://github.phodal.com/#redis) + * [邻近算法与相似用户](http://github.phodal.com/#邻近算法与相似用户) +* [如何在 GitHub “寻找灵感(fork)”](http://github.phodal.com/#如何在github寻找灵感fork) + * [Lettuce 构建过程](http://github.phodal.com/#lettuce构建过程) + * [需求](http://github.phodal.com/#需求) + * [计划](http://github.phodal.com/#计划) + * [实现第一个需求](http://github.phodal.com/#实现第一个需求) + * [实现第二个需求](http://github.phodal.com/#实现第二个需求) +* [如何以“正确的姿势”阅读开源软件代码](http://github.phodal.com/#如何以正确的姿势阅读开源软件代码) + * [阅读过程](http://github.phodal.com/#阅读过程) + * [示例](http://github.phodal.com/#示例) +* [GitHub 连击](http://github.phodal.com/#github连击) + * [100 天](http://github.phodal.com/#天) + * [40 天的提升](http://github.phodal.com/#天的提升) + * [100 天的挑战](http://github.phodal.com/#天的挑战) + * [140 天的希冀](http://github.phodal.com/#天的希冀) + * [200 天的 Showcase](http://github.phodal.com/#天的showcase) + * [一些项目简述](http://github.phodal.com/#一些项目简述) + * [Google Maps solr polygon 搜索](http://github.phodal.com/#google-map-solr-polygon-搜索) + * [技能树](http://github.phodal.com/#技能树) + * [365 天](http://github.phodal.com/#天-1) + * [编程的基础能力](http://github.phodal.com/#编程的基础能力) + * [技术与框架设计](http://github.phodal.com/#技术与框架设计) + * [领域与练习](http://github.phodal.com/#领域与练习) + * [其他](http://github.phodal.com/#其他-1) + * [500 天](http://github.phodal.com/#天-2) + * [500 天与 10000 小时](http://github.phodal.com/#天与10000小时) + * [编程的情绪周期](http://github.phodal.com/#编程的情绪周期) + * [有意图的练习](http://github.phodal.com/#有意图的练习) + * [预见性练习](http://github.phodal.com/#预见性练习) + * [小结](http://github.phodal.com/#小结) + * [365*2-7 天里](http://github.phodal.com/#天里) + * [编码的练习](http://github.phodal.com/#编码的练习) + * [See you Again](http://github.phodal.com/#see-you-again) +* [GitHub 里程碑](http://github.phodal.com/#github-里程碑) + * [写在 GitHub 的第 19999 个 Star 时](http://github.phodal.com/#写在github-的第-19999-个-star-时) + * [从创建开源框架说起](http://github.phodal.com/#从创建开源框架说起) + * [下一个开源项目](http://github.phodal.com/#下一个开源项目) +* [GitHub 寻宝指南](http://github.phodal.com/#github-寻宝指南) + * [寻找 Demo 节省时间](http://github.phodal.com/#寻找-demo-节省时间) + * [寻找脚手架:加快前期开发](http://github.phodal.com/#寻找脚手架加快前期开发) + * [寻找 awesome-xxx:探索可能性](http://github.phodal.com/#寻找-awesome-xxx探索可能性) + * [**模仿轮子**的轮子](http://github.phodal.com/#模仿轮子的轮子) + * [学习资源](http://github.phodal.com/#学习资源) + * [密钥/密码](http://github.phodal.com/#密钥密码) + * [私有、商用的 SDK 或代码](http://github.phodal.com/#私有商用的-sdk-或代码) + * [数据及数据制作工具](http://github.phodal.com/#数据及数据制作工具) + * [结论](#结论) +* [GitHub 获 Star 指南](#github-获-star-指南) + * [为什么我们 Star 一个项目](#为什么我们-star-一个项目) + * [我的获 Star 方式](#我的获-star-方式) + * [GitHub 流量分析](#github-流量分析) + * [GitHub 获 Star 指南技巧](#github-获-star-指南技巧) + * [技巧一:结合 SEO 技巧](#技巧一结合-seo-技巧) + * [技巧二:完整、易读的 README](#技巧二完整易读的-readme) + * [技巧三:社交分享](#技巧三社交分享) + * [技巧四:文章](#技巧四文章) + * [技巧五:把握 GitHub Trending](#技巧五把握-github-trending) + * [不是技巧的技巧:持续性](#不是技巧的技巧持续性) +* [FAQ](#faq) + * [如何看待 GitHub 项目刷 Star 行为?](http://github.phodal.com/#如何看待github-项目刷star行为) + +## License + +[![Phodal's Book](http://brand.phodal.com/shields/book-small.svg)](https://www.phodal.com/) + +© 2015~2019 [Phodal Huang](https://www.phodal.com). This code is distributed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License. See `LICENSE` in this directory. + +[![待我代码编成,娶你为妻可好](http://brand.phodal.com/slogan/slogan.svg)](http://www.xuntayizhan.com/person/ji-ke-ai-qing-zhi-er-shi-dai-wo-dai-ma-bian-cheng-qu-ni-wei-qi-ke-hao-wan/) diff --git a/docs/README.md b/docs/README.md index 2f86d57..68b514a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,13 @@ -# 首页 +# GitHub 漫游指南 -> An awesome project. +> 漫游,即随意游玩~。 + +在线阅读:[GitHub 漫游指南](http://github.phodal.com/),下载:[pdf](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.pdf)、[mobi](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.mobi)、[epub](https://github.com/phodal/github-roam/raw/gh-pages/github-roam.epub) + +2014 年,写了《[一步步搭建物联网系统](https://github.com/phodal/designiot)》(电子书)。 + +2015.3.9 号,想着写个《[GitHub 漫游指南](http://github.phodal.com/)》,于是在最开始的地方写着: + +> 我的 GitHub 主页上写着加入的时间——``Joined on Nov 8, 2010``,那时才大一。在那之后的日子里,也许是因为我学的不是计算机的关系,并没有熟练使用它。到了今天——``2015.3.9``,我发现 GitHub 是程序员的社交网站。 + +但是过了很久都没有动静,今天是 2015.10.24,我想是时候完成这个目标了。 \ No newline at end of file diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 0000000..a0dee0a --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,3 @@ + + +* [开始阅读](chapter/Github漫游指南.md) \ No newline at end of file diff --git a/docs/chapter/Github漫游指南.md b/docs/chapter/Github漫游指南.md new file mode 100644 index 0000000..24bdc50 --- /dev/null +++ b/docs/chapter/Github漫游指南.md @@ -0,0 +1,4003 @@ +前言 +=== + +关于作者 +--- + +黄峰达(Phodal Huang)是一个创客、工程师、咨询师和作家。他毕业于西安文理学院电子信息工程专业,现作为一个咨询师就职于 ThoughtWorks 深圳。长期活跃于开源软件社区 GitHub,目前专注于物联网和前端领域。 + +作为一个开源软件作者,著有 Growth、Stepping、Lan、Echoesworks 等软件。其中开源学习应用 Growth,广受读者和用户好评,可在 App Store 及各大 Android 应用商店下载。 + +作为一个技术作者,著有《自己动手设计物联网》(电子工业出版社)、《全栈应用开发:精益实践》(电子工业出版社,正在出版)。并在 GitHub 上开源有《Growth:全栈增长工程师指南》、《GitHub 漫游指南》等七本电子书。 + +作为技术专家,他为英国 Packt 出版社审阅有物联网书籍《Learning IoT》、《Smart IoT》,前端书籍《Angular 2 Serices》、《Getting started with Angular》等技术书籍。 + +他热爱编程、写作、设计、旅行、hacking,你可以从他的个人网站:[https://www.phodal.com/](https://www.phodal.com/) 了解到更多的内容。 + +其它相关信息: + + - 微博:[http://weibo.com/phodal](http://weibo.com/phodal) + - GitHub:[https://github.com/phodal](https://github.com/phodal) + - 知乎:[https://www.zhihu.com/people/phodal](https://www.zhihu.com/people/phodal) + - SegmentFault:[https://segmentfault.com/u/phodal](https://segmentfault.com/u/phodal) + +当前为预览版,在使用的过程中遇到任何问题请及时与我联系。阅读过程中的问题,不妨在 GitHub 上提出来:[Issues](https://github.com/phodal/github/issues) + +阅读过程中遇到语法错误、拼写错误、技术错误等等,不妨来个 Pull Request,这样可以帮助到其他阅读这本电子书的童鞋。 + +我的电子书: + + * 《[GitHub 漫游指南](https://github.com/phodal/github-roam)》 + * 《[我的职业是前端工程师](https://github.com/phodal/fe)》 + * 《[Serverless 架构应用开发指南](https://github.com/phodal/serverless)》 + * 《[Growth:全栈增长工程师指南](https://github.com/phodal/growth-ebook)》 + * 《[Phodal's Idea 实战指南](https://github.com/phodal/ideabook)》 + * 《[一步步搭建物联网系统](https://github.com/phodal/designiot)》 + * 《[RePractise](https://github.com/phodal/repractise)》 + * 《[Growth:全栈增长工程师实战](https://github.com/phodal/growth-in-action)》 + +我的微信公众号: + +![作者微信公众号:phodal-weixin](./img/wechat.jpg) + +我的 GitHub 主页上写着加入的时间——``Joined on Nov 8, 2010``,那时才大一,在那之后的那么长的日子里我都没有登录过。也许是因为我学的不是计算机,到了今天——``2015.3.9``,我才发现这其实是程序员的社交网站。 + +过去,曾经有很长的一些时间我试过在 GitHub 上连击,也试着去了解别人是如何用好这个工具的。当然粉丝在 GitHub 上也是很重要的。 + +在这里,我会试着将我在 GitHub 上学到的东西一一分享出来。 + +## 我与 GitHub 的故事 + +在我大四找工作的时候,试图去寻找一份硬件、物联网相关的工作(PS:专业是电子信息工程)。尽管简历上写得满满的各种经历、经验,然而并没有卵用。跑了几场校园招聘会后,十份简历(PS:事先已经有心里准备)一个也没有投出去——因为学校直接被拒。我对霸面什么的一点兴趣都没有,千里马需要伯乐。后来,我加入了[Martin Flower](https://martinfowler.com/)所在的公司,当然这是后话了。 + +这是一个残酷的世界,在学生时代,如果你长得不帅不高的话,那么多数的附加技能都是白搭(PS:通常富的是看不到这篇文章的)。在工作时期,如果你上家没有名气,那么将会影响你下一份工作的待遇。而,很多东西却可以改变这些,GitHub 就是其中一个。 + +注册 GitHub 的时候大概是大一的时候,我熟悉的时候已经是大四了,现在已经毕业一年了。在过去的近两年里,我试着以几个维度在 GitHub 上创建项目: + +1. 快速上手框架来实战,即 demo +2. 重构别人的代码 +3. 创建自己可用的框架 +4. 快速构建大型应用 +5. 构建通用的框架 + +### GitHub 与收获 + +先说说**与技能无关的收获**吧,毕业设计做的是一个《[最小物联网系统](https://github.com/phodal/iot)》,考虑到我们专业老师没有这方面知识,答辩时会带来问题,尽量往这方面靠拢。当我毕业后,这个项目已经有过百个 Star 了,这样易上手的东西还是比较受欢迎的(PS:不过这种硬件相关的项目通常受限于GitHub上硬件开发工程师比较少的困扰)。 + +毕业后一个月收到 PACKT 出版社的邮件(PS:他们是在 GitHub 上找到我的),内容是关于 Review 一本[物联网](iot)书籍,即在《[从 Review 到翻译 IT书籍](http://www.phodal.com/blog/review-it-books-with-translate-book/)》中提到的《Learning Internet of Things》。作为一个四级没过的"物联网专家",去审阅一本英文的物联网书籍。。。 + +当然,后来是审阅完了,书上有我的英文简介。 + +![Phodal Huang Introduction](./img/phodal-intro.jpg) + +一个月前,收到 MANNING 出版社的邮件(PS:也是在 GitHub 上),关于 Review 一本[物联网](iot)书籍的目录,并提出建议。 + +也因此带来了其他更多的东西,当然不是这里的主题。在这里,我们就不讨论各种骚扰邮件,或者中文合作。从没有想象过,我也可以在英语世界有一片小天地。 + +这些告诉我们,GitHub 上找一个你擅长的主题,那么会有很多人找上你的。 + +### GitHub 与成长 + +过去写过一篇《[如何通过 GitHub 提升自己](http://www.phodal.com/blog/use-github-grow-self/)》的文章,现在只想说三点: + +1. 测试 +2. 更多的测试 +3. 更多的、更多的、更多的测试 + +没有测试的项目是很扯淡的,除非你的项目只有一个函数,然后那个函数返回``Hello,World``。 + +如果你的项目代码有上千行,如果你能保证测试覆盖率可以达到95%以的话,那么我想你的项目不会有太复杂的函数。假使有这样的函数,那么它也是被测试覆盖住的。 + +如果你在用心做这个项目,那么你看到代码写得不好也会试着改进,即重构。当有了一些,你的技能会不断提升。你开始会试着接触更多的东西,如 stub,如 mock,如 fakeserver。 + +有一天,你会发现你离不开测试。 + +然后就会相信:**那些没有写测试的项目都是在耍流氓** + +## 为什么你应该深入 GitHub + +上面我们说的都是我们可以收获到的东西,我们开始尝试就意味着我们知道它可能给我们带来好处。上面已经提到很多可以提升自己的例子了,这里再说说其他的。 + +### 方便工作 + +我们可以从中获取到不同的知识、内容、信息。每个人都可以从别人的代码中学习,当我们需要构建一个库的时候,我们可以在上面寻找不同的库和代码来实现我们的功能。如当我在实现一个库的时候,我会在 GitHub 上找到相应的组件: + +- Promise 支持 +- Class 类(PS:没有一个好的类使用的方式) +- Template 一个简单的模板引擎 +- Router 用来控制页面的路由 +- Ajax 基本的 Ajax Get/Post 请求 + +### 获得一份工作 + +越来越多的人因为 GitHub 获得工作,因为他们的做的东西正好符合一些公司的要求。那么,这些公司在寻找代码的时候,就会试着邀请他们。 + +因而,在 GitHub 寻找合适的候选人,已经是一种趋势。 + +### 扩大交际 + +如果我们想创造出更好、强大地框架时,那么认识更多的人可能会带来更多的帮助。有时候会同上面那一点一样的效果 + +# 介绍 + +## Github + +Wiki百科上是这么说的 + +> GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目。它由GitHub公司(曾称Logical Awesome)的开发者Chris Wanstrath、PJ Hyett和Tom Preston-Werner +使用Ruby on Rails编写而成。 + +当然让我们看看官方的介绍: + +> GitHub is the best place to share code with friends, co-workers, classmates, and complete strangers. Over eight million people use GitHub to build amazing things together. + + +它还是什么? + +- 网站 +- 免费博客 +- 管理配置文件 +- 收集资料 +- 简历 +- 管理代码片段 +- 托管编程环境 +- 写作 + +等等。看上去像是大餐,但是你还需要了解点什么? + +### 版本管理与软件部署 + +jQuery[^jQuery]在发布版本``2.1.3``,一共有152个commit。我们可以看到如下的提交信息: + + - Ajax: Always use script injection in globalEval … bbdfbb4 + - Effects: Reintroduce use of requestAnimationFrame … 72119e0 + - Effects: Improve raf logic … 708764f + - Build: Move test to appropriate module fbdbb6f + - Build: Update commitplease dev dependency + - ... + +### Github与Git + +> Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理。在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中。目前,包括Rubinius、Merb和Bitcoin在内的很多知名项目都使用了Git。Git同样可以被诸如Capistrano和Vlad the Deployer这样的部署工具所使用。 + +> GitHub可以托管各种git库,并提供一个web界面,但与其它像 SourceForge或Google Code这样的服务不同,GitHub的独特卖点在于从另外一个项目进行分支的简易性。为一个项目贡献代码非常简单:首先点击项目站点的“fork”的按钮,然后将代码检出并将修改加入到刚才分出的代码库中,最后通过内建的“pull request”机制向项目负责人申请代码合并。已经有人将GitHub称为代码玩家的MySpace。 + +[^jQuery]: jQuery是一套跨浏览器的JavaScript库,简化HTML与JavaScript之间的操作。 + +## 用好Github + +如何用好Github,并实践一些敏捷软件开发是一个很有意思的事情.我们可以在上面做很多事情,从测试到CI,再到自动部署. + +### 敏捷软件开发 + +显然我是在扯淡,这和敏捷软件开发没有什么关系。不过我也不知道瀑布流是怎样的。说说我所知道的一个项目的组成吧: + + - 看板式管理应用程序(如trello,简单地说就是管理软件功能) + - CI(持续集成) + - 测试覆盖率 + - 代码质量(code smell) + +对于一个不是远程的团队(如只有一个人的项目) 来说,Trello、Jenkin、Jira不是必需的: + +> 你存在,我深深的脑海里 + +当只有一个人的时候,你只需要明确知道自己想要什么就够了。我们还需要的是CI、测试,以来提升代码的质量。 + +### 测试 + +通常我们都会找Document,如果没有的话,你会找什么?看源代码,还是看测试? + +```javascript +it("specifying response when you need it", function (done) { + var doneFn = jasmine.createSpy("success"); + + lettuce.get('/some/cool/url', function (result) { + expect(result).toEqual("awesome response"); + done(); + }); + + expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url'); + expect(doneFn).not.toHaveBeenCalled(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + "status": 200, + "contentType": 'text/plain', + "responseText": 'awesome response' + }); +}); +``` + +代码来源: [https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +上面的测试用例,清清楚楚地写明了用法,虽然写得有点扯。 + +等等,测试是用来干什么的。那么,先说说我为什么会想去写测试吧: + + - 我不希望每次做完一个个新功能的时候,再手动地去测试一个个功能。(自动化测试) + - 我不希望在重构的时候发现破坏了原来的功能,而我还一无所知。 + - 我不敢push代码,因为我没有把握。 + +虽然,我不是TDD的死忠,测试的目的是保证功能正常,TDD没法让我们写出质量更高的代码。但是有时TDD是不错的,可以让我们写出逻辑更简单地代码。 + +也许你已经知道了``Selenium``、``Jasmine``、``Cucumber``等等的框架,看到过类似于下面的测试 + +``` + Ajax + ✓ specifying response when you need it + ✓ specifying html when you need it + ✓ should be post to some where + Class + ✓ respects instanceof + ✓ inherits methods (also super) + ✓ extend methods + Effect + ✓ should be able fadein elements + ✓ should be able fadeout elements +``` + +代码来源: [https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +看上去似乎每个测试都很小,不过补完每一个测试之后我们就得到了测试覆盖率 + +File | Statements | Branches | Functions | Lines +-----|------------|----------|-----------|------ +lettuce.js | 98.58% (209 / 212)| 82.98%(78 / 94) | 100.00% (54 / 54) | 98.58% (209 / 212) + +本地测试都通过了,于是我们添加了``Travis-CI``来跑我们的测试 + +### CI + +虽然node.js不算是一门语言,但是因为我们用的node,下面的是一个简单的``.travis.yml``示例: + +```yml +language: node_js +node_js: + - "0.10" + +notifications: + email: false + +before_install: npm install -g grunt-cli +install: npm install +after_success: CODECLIMATE_REPO_TOKEN=321480822fc37deb0de70a11931b4cb6a2a3cc411680e8f4569936ac8ffbb0ab codeclimate < coverage/lcov.info +``` + +代码来源: [https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +我们把这些集成到``README.md``之后,就有了之前那张图。 + +CI对于一个开发者在不同城市开发同一项目上来说是很重要的,这意味着当你添加的部分功能有测试覆盖的时候,项目代码会更加强壮。 + +### 代码质量 + +像``jslint``这类的工具,只能保证代码在语法上是正确的,但是不能保证你没有写一堆bad smell的代码。 + + - 重复代码 + - 过长的函数 + - 等等 + +``Code Climate``是一个与github集成的工具,我们不仅仅可以看到测试覆盖率,还有代码质量。 + +先看看上面的ajax类: + +```javascript +Lettuce.get = function (url, callback) { + Lettuce.send(url, 'GET', callback); +}; + +Lettuce.send = function (url, method, callback, data) { + data = data || null; + var request = new XMLHttpRequest(); + if (callback instanceof Function) { + request.onreadystatechange = function () { + if (request.readyState === 4 && (request.status === 200 || request.status === 0)) { + callback(request.responseText); + } + }; + } + request.open(method, url, true); + if (data instanceof Object) { + data = JSON.stringify(data); + request.setRequestHeader('Content-Type', 'application/json'); + } + request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + request.send(data); +}; +``` + +代码来源: [https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +在[Code Climate](https://codeclimate.com/github/phodal/lettuce/src/ajax.js)在出现了一堆问题 + + - Missing "use strict" statement. (Line 2) + - Missing "use strict" statement. (Line 14) + - 'Lettuce' is not defined. (Line 5) + +而这些都是小问题啦,有时可能会有 + + - Similar code found in two :expression_statement nodes (mass = 86) + +这就意味着我们可以对上面的代码进行重构,他们是重复的代码。 + +### 重构 + +不想在这里说太多关于``重构``的东西,可以参考Martin Flower的《重构》一书去多了解一些重构的细节。 + +这时想说的是,只有代码被测试覆盖住了,那么才能保证重构的过程没有出错。 + +创建开源项目 +=== + +人们出于不同的目的来创建开源项目,可不论目的是什么,过程都是一样的。 + +1. 首先,我们需要为我们的项目取一个名字。 +2. 然后,为我们的开源项目选择一个合适的 LICENSE +3. 然后再去创建项目 + +取一个好的名字 +--- + +取名字,从来就不是一件容易的事。 + +因此,我就长话短说,一般就是取一个有意义的名字,当然没有意义也没有任何问题。 + +通常而言,如果自己计划有一系列的开源项目,那么我们可以保持一定的命名规则。 + +挑选好 LICENSE +--- + +> 在二十世纪而七十年代末和八十年代初,为了防止自己的软件被竞争对手所使用,大多数厂家停止分发其软件源代码,并开始使用版权和限制性软件许可证,来限制或者禁止软件源代码的复制或再分配。随后,Richard Matthew Stallman(Richard Matthew Stallman)发起了自由软件运动,他开创了 Copyleft 的概念:使用版权法的原则来保护使用、修改和分发自由软件的权利,并且是描述这些术语的自由软件许可证的主要作者。最为人所称道的是GPL(被广泛使用的自由软件协议)。[^rms] + +(PS:关于自由软件及 RMS 的更多信息、历史,可以阅读《若为自由故:自由软件之父 - 理查德 斯托曼传》) + +[^rms]: https://zh.wikipedia.org/wiki/%E7%90%86%E6%9F%A5%E5%BE%B7%C2%B7%E6%96%AF%E6%89%98%E6%9B%BC + +随后,便诞生了开源软件的概念,开源的要求比自由软件宽松一些[^gnu_gpl]。迄今发布的自由软件源代码都是开源软件,而并非所有的开源软件都是自由软件。这是因为不同的许可(协议)赋予用户不同的权利,如 GPL 协议强制要求开源修改过源码的代码,而宽松一点的 MIT 则不会有这种要求。 + +[^gnu_gpl]: https://www.gnu.org/philosophy/open-source-misses-the-point.zh-cn.html + +如下是不同开源许可证的市场占有率及使用情况。 + +![License 使用情况](./img/permissive-vs-copylift-license-2.jpg) + +又比如,在我们看到的一些外版书籍上,如果拥有代码。那么作者一般就会在前言或者类似的位置里,指明书中代码的版权所属。如: + +> 也许你需要在自己的程序或文档中用到本书的代码,但除非大篇幅地使用,否则不必与我们联系取得授权。例如,用本书中的几段代码编写程序无需请求许可,blabla。 + +于是,选择一个合理的 LICENSE,就变成了一个有趣的话题。为此,笔者做了一个如何进行开源协议选型的流程图: + +[![如何选择 License](./img/licenses.png)](https://github.com/phodal/licenses) + +简单地来说,这些 License 之间是一些权利的区别,如当你把代码放置到公有领域,就意味着任何人可以修改,并且不需要标明出注;可如果你想要别人标明出处及作者,你就需要 MIT 协议;而你希望别人闭源的话,那么你就需要 MPL 协议等等。 + +那么,下面让我们简单地介绍一下不同的几个协议。 + +### 公有领域 + +> WTFPL(Do What The Fuck You Want To Public License,中文译名:你他妈的想干嘛就干嘛公共许可证)是一种不太常用的、极度放任的自由软件许可证。它的条款基本等同于贡献到公有领域。[^wtfpl] + +[^wtfpl]: https://zh.wikipedia.org/wiki/WTFPL + +这就意味着,对于拿到这些代码的其他人,他们想怎么修改就可以怎么修改。 + +### GPL + +由于 GPL 的传染性,便意味着,他人引用我们的代码时,其所写的代码也需要使用 GPL 开源。即:GPL 是有 “传染性” 的 “病毒” ,因为 GPL 条款规定演绎作品也必须是 GPL 的。 + +而如果我们只针对的是,他人可以使用库,而不开源,则可以用 LGPL。但是修改库则不适用。 + +### MIT + +因此,一般而言,我使用的是 MIT 协议。至少我保留了一个署名权,即你可以修改我的代码,但是在 LICENSE 里必须加上我的名字。 + +选用 MIT 特别有意思,特别是在最近几年里,发生过: + + - [iView “抄袭” Element UI 事件](https://zhuanlan.zhihu.com/p/25739512) + - [AndroidTVLauncher “抄袭” 事件](https://github.com/JackyAndroid/AndroidTVLauncher/issues/22) + +等等。这告诫了我们,如果你不想要有这种经历,那么就不要用 MIT 了。 + +### Creative Commons + +是的,当我写 Markdown 的时候,考虑到未来会以纸质书的形式出现,便会使用 CC-BY-NC-ND 协议: + + - CC -> Creative Commons + - BY -> 署名(英语:Attribution,by) + - NC -> 非商业性使用(英语:NonCommercial) + - ND -> 禁止演绎(英语:NoDerivs)。 + +即,任何人可以使用我写的电子书来自由复制、散布、展示及演出,但是不得用于商业用途(作者本人可以)。它可以随意地放在他的博客上,他的各个文章里。但是必须标明出自,并且不得改变、转变或更改本作品。 + +如果你不介意的话,你可以使用公有领域(Public Domain)。可是这样一来,万一有一天,别人直接拿你的作品出书,你就骂爹了。 + +# Git 基本知识与 GitHub 使用 + +## Git + +从一般开发者的角度来看,Git 有以下功能: + +1. 从服务器上克隆数据库(包括代码和版本信息)到单机上。 +2. 在自己的机器上创建分支,修改代码。 +3. 在单机上自己创建的分支上提交代码。 +4. 在单机上合并分支。 +5. 新建一个分支,把服务器上最新版的代码 fetch 下来,然后跟自己的主分支合并。 +6. 生成补丁(patch),把补丁发送给主开发者。 +7. 看主开发者的反馈,如果主开发者发现两个一般开发者之间有冲突(他们之间可以合作解决的冲突),就会要求他们先解决冲突,然后再由其中一个人提交。如果主开发者可以自己解决,或者没有冲突,就通过。 +8. 一般开发者之间解决冲突的方法,开发者之间可以使用 pull 命令解决冲突,解决完冲突之后再向主开发者提交补丁。 + +从主开发者的角度(假设主开发者不用开发代码)看,Git 有以下功能: + +1. 查看邮件或者通过其它方式查看一般开发者的提交状态。 +2. 打上补丁,解决冲突(可以自己解决,也可以要求开发者之间解决以后再重新提交,如果是开源项目,还要决定哪些补丁有用,哪些不用)。 +3. 向公共服务器提交结果,然后通知所有开发人员。 + +### Git 初入 + +如果是第一次使用 Git,你需要设置署名和邮箱: + +``` +$ git config --global user.name "用户名" +$ git config --global user.email "电子邮箱" +``` + +将代码仓库 clone 到本地,其实就是将代码复制到你的机器里,并交由 Git 来管理: + +``` +$ git clone git@github.com:someone/symfony-docs-chs.git +``` + +你可以修改复制到本地的代码了(symfony-docs-chs 项目里都是 rst 格式的文档)。当你觉得完成了一定的工作量,想做个阶段性的提交: + +向这个本地的代码仓库添加当前目录的所有改动: + +``` +$ git add . +``` + +或者只是添加某个文件: + +``` +$ git add -p +```` + +我们可以输入 + +``` +$git status +``` + +来看现在的状态,如下图是添加之前的: + +![Before add](./img/before-add.png) + +下面是添加之后 的 + +![After add](./img/after-add.png) + +可以看到状态的变化是从黄色到绿色,即 unstage 到 add。 + + +## GitHub + +Wiki 百科上是这么说的 + +> GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目。它由GitHub公司(曾称Logical Awesome)的开发者Chris Wanstrath、PJ Hyett和Tom Preston-Werner +使用Ruby on Rails编写而成。 + +当然让我们看看官方的介绍: + +> GitHub is the best place to share code with friends, co-workers, classmates, and complete strangers. Over eight million people use GitHub to build amazing things together. + + +它还是什么? + +- 网站 +- 免费博客 +- 管理配置文件 +- 收集资料 +- 简历 +- 管理代码片段 +- 托管编程环境 +- 写作 + +等等。看上去像是大餐,但是你还需要了解点什么? + +### 版本管理与软件部署 + +jQuery[^jQuery] 在发布版本``2.1.3``,一共有 152 个 commit。我们可以看到如下的提交信息: + + - Ajax: Always use script injection in globalEval … bbdfbb4 + - Effects: Reintroduce use of requestAnimationFrame … 72119e0 + - Effects: Improve raf logic … 708764f + - Build: Move test to appropriate module fbdbb6f + - Build: Update commitplease dev dependency + - ... + +### GitHub 与 Git + +> Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理。在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中。目前,包括Rubinius、Merb和Bitcoin在内的很多知名项目都使用了Git。Git同样可以被诸如Capistrano和Vlad the Deployer这样的部署工具所使用。 + +> GitHub可以托管各种git库,并提供一个web界面,但与其它像 SourceForge或Google Code这样的服务不同,GitHub的独特卖点在于从另外一个项目进行分支的简易性。为一个项目贡献代码非常简单:首先点击项目站点的“fork”的按钮,然后将代码检出并将修改加入到刚才分出的代码库中,最后通过内建的“pull request”机制向项目负责人申请代码合并。已经有人将GitHub称为代码玩家的MySpace。 + +### 在 GitHub 创建项目 + +接着,我们试试在上面创建一个项目: + +![GitHub Roam](./img/github-roam-create.jpg) + +就会有下面的提醒: + +![GitHub Roam](./img/project-init.jpg) + +它提供多种方式的创建方法: + +> …or create a new repository on the command line + +``` +echo "# github-roam" >> README.md +git init +git add README.md +git commit -m "first commit" +git remote add origin git@github.com:phodal/github-roam.git +git push -u origin master +``` + +> …or push an existing repository from the command line + +``` +git remote add origin git@github.com:phodal/github-roam.git +git push -u origin master +``` + +如果你完成了上面的步骤之后,那么我想你想知道你需要怎样的项目。 + +## GitHub 流行项目分析 + +之前曾经分析过一些 GitHub 的用户行为,现在我们先来说说 GitHub 上的 Star 吧。(截止:2015年3月9日23时。) + +用户 | 项目名 | Language | Star | Url +-----|---------- |----------|------|---- +twbs | Bootstrap | CSS | 78490 | [https://github.com/twbs/bootstrap](https://github.com/twbs/bootstrap) +vhf |free-programming books | - | 37240 | [https://github.com/vhf/free-programming-books](https://github.com/vhf/free-programming-books) +angular | angular.js | JavaScript | 36,061 | [https://github.com/angular/angular.js](https://github.com/angular/angular.js) +mbostock | d3 | JavaScript | 35,257 | [https://github.com/mbostock/d3](https://github.com/mbostock/d3) +joyent | node | JavaScript | 35,077 | [https://github.com/joyent/node](https://github.com/joyent/node) + +上面列出来的是前5的,看看大于 1 万个 Stars 的项目的分布,一共有 82 个: + +语言 | 项目数 +-----|----- +JavaScript | 37 +Ruby | 6 +CSS | 6 +Python | 4 +HTML | 3 +C++ | 3 +VimL | 2 +Shell | 2 +Go | 2 +C | 2 + +类型分布: + + + - 库和框架:如``jQuery`` + - 系统:如``Linux``、``hhvm``、``docker`` + - 配置集:如``dotfiles`` + - 辅助工具:如``oh-my-zsh`` + - 工具:如``Homewbrew``和``Bower`` + - 资料收集:如``free programming books``,``You-Dont-Know-JS``,``Font-Awesome`` + - 其他:简历如``Resume`` + +## Pull Request + +除了创建项目之外,我们也可以创建 Pull Request 来做贡献。 + +### 我的第一个 PR + +我的第一个 PR 是给一个小的 Node 的 CoAP 相关的库的 Pull Request。原因比较简单,是因为它的 README.md 写错了,导致我无法进行下一步。 + + const dgram = require('dgram') + - , coapPacket = require('coap-packet') + + , package = require('coap-packet') + +很简单,却又很有用的步骤,另外一个也是: + +``` + else + cat << END + $0: error: module ngx_pagespeed requires the pagespeed optimization library. +-Look in obj/autoconf.err for more details. ++Look in objs/autoconf.err for more details. + END + exit 1 + fi +``` + +### CLA + +CLA 即 Contributor License Agreement,在为一些大的组织、机构提交 Pull Request 的时候,可能需要签署这个协议。他们会在你的 Pull Request 里问你,只有你到他们的网站去注册并同意协议才会接受你的 PR。 + +以下是我为 Google 提交的一个 PR + +![Google CLA](./img/google-cla.png) + +以及 Eclipse 的一个 PR + +![Eclipse CLA](./img/eclipse-cla.png) + +他们都要求我签署 CLA。 + +# 构建 GitHub 项目 + +## 如何用好 GitHub + +如何用好 GitHub,并实践一些敏捷软件开发是一个很有意思的事情.我们可以在上面做很多事情,从测试到 CI,再到自动部署. + +### 敏捷软件开发 + +显然我是在扯淡,这和敏捷软件开发没有什么关系。不过我也不知道瀑布流是怎样的。说说我所知道的一个项目的组成吧: + + - 看板式管理应用程序(如 trello,简单地说就是管理软件功能) + - CI(持续集成) + - 测试覆盖率 + - 代码质量(code smell) + +对于一个不是远程的团队(如只有一个人的项目)来说,Trello、Jenkin、Jira不是必需的: + +> 你存在,我深深的脑海里 + +当只有一个人的时候,你只需要明确知道自己想要什么就够了。我们还需要的是 CI、测试,以来提升代码的质量。 + +### 测试 + +通常我们都会找 Document,如果没有的话,你会找什么?看源代码,还是看测试? + +```javascript +it("specifying response when you need it", function (done) { + var doneFn = jasmine.createSpy("success"); + + lettuce.get('/some/cool/url', function (result) { + expect(result).toEqual("awesome response"); + done(); + }); + + expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url'); + expect(doneFn).not.toHaveBeenCalled(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + "status": 200, + "contentType": 'text/plain', + "responseText": 'awesome response' + }); +}); +``` + +代码来源:[https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +上面的测试用例,清清楚楚地写明了用法,虽然写得有点扯。 + +等等,测试是用来干什么的。那么,先说说我为什么会想去写测试吧: + + - 我不希望每次做完一个个新功能的时候,再手动地去测试一个个功能。(自动化测试) + - 我不希望在重构的时候发现破坏了原来的功能,而我还一无所知。 + - 我不敢push代码,因为我没有把握。 + +虽然,我不是 TDD 的死忠,测试的目的是保证功能正常,TDD 没法让我们写出质量更高的代码。但是有时TDD是不错的,可以让我们写出逻辑更简单地代码。 + +也许你已经知道了``Selenium``、``Jasmine``、``Cucumber``等等的框架,看到过类似于下面的测试 + +``` + Ajax + ✓ specifying response when you need it + ✓ specifying html when you need it + ✓ should be post to some where + Class + ✓ respects instanceof + ✓ inherits methods (also super) + ✓ extend methods + Effect + ✓ should be able fadein elements + ✓ should be able fadeout elements +``` + +代码来源:[https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +看上去似乎每个测试都很小,不过补完每一个测试之后我们就得到了测试覆盖率 + +File | Statements | Branches | Functions | Lines +-----|------------|----------|-----------|------ +lettuce.js | 98.58% (209 / 212)| 82.98%(78 / 94) | 100.00% (54 / 54) | 98.58% (209 / 212) + +本地测试都通过了,于是我们添加了``Travis-CI``来跑我们的测试 + +### CI + +虽然 node.js 不算是一门语言,但是因为我们用的 node,下面的是一个简单的 ``.travis.yml`` 示例: + +```yml +language: node_js +node_js: + - "0.10" + +notifications: + email: false + +before_install: npm install -g grunt-cli +install: npm install +after_success: CODECLIMATE_REPO_TOKEN=321480822fc37deb0de70a11931b4cb6a2a3cc411680e8f4569936ac8ffbb0ab codeclimate < coverage/lcov.info +``` + +代码来源:[https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +我们把这些集成到 ``README.md`` 之后,就有了之前那张图。 + +CI对于一个开发者在不同城市开发同一项目上来说是很重要的,这意味着当你添加的部分功能有测试覆盖的时候,项目代码会更加强壮。 + +### 代码质量 + +像 ``jslint`` 这类的工具,只能保证代码在语法上是正确的,但是不能保证你写了一堆 bad smell 的代码。 + + - 重复代码 + - 过长的函数 + - 等等 + +``Code Climate`` 是一个与 GitHub 集成的工具,我们不仅仅可以看到测试覆盖率,还有代码质量。 + +先看看上面的 ajax 类: + +```javascript +Lettuce.get = function (url, callback) { + Lettuce.send(url, 'GET', callback); +}; + +Lettuce.send = function (url, method, callback, data) { + data = data || null; + var request = new XMLHttpRequest(); + if (callback instanceof Function) { + request.onreadystatechange = function () { + if (request.readyState === 4 && (request.status === 200 || request.status === 0)) { + callback(request.responseText); + } + }; + } + request.open(method, url, true); + if (data instanceof Object) { + data = JSON.stringify(data); + request.setRequestHeader('Content-Type', 'application/json'); + } + request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + request.send(data); +}; +``` + +代码来源:[https://github.com/phodal/lettuce](https://github.com/phodal/lettuce) + +在 [Code Climate](https://codeclimate.com/github/phodal/lettuce/src/ajax.js) 在出现了一堆问题 + + - Missing "use strict" statement. (Line 2) + - Missing "use strict" statement. (Line 14) + - 'Lettuce' is not defined. (Line 5) + +而这些都是小问题啦,有时可能会有 + + - Similar code found in two :expression_statement nodes (mass = 86) + +这就意味着我们可以对上面的代码进行重构,他们是重复的代码。 + +## 模块分离与测试 + +在之前说到 + +> 奋斗了近半个月后,将 fork 的代码读懂、重构、升级版本、调整,添加新功能、添加测试、添加 CI、添加分享之后,终于 almost finish。 + +今天就来说说是怎样做的。 + +以之前造的 [Lettuce](https://github.com/phodal/lettuce) 为例,里面有: + + - 代码质量(Code Climate) + - CI状态(Travis CI) + - 测试覆盖率(96%) + - 自动化测试(npm test) + - 文档 + +按照 [Web Developer 路线图](https://github.com/phodal/awesome-developer)来说,我们还需要有: + + - 版本管理 + - 自动部署 + +等等。 + +### 代码模块化 + +在 SkillTree 的源码里,大致分为三部分: + + - namespace 函数:顾名思义 + - Calculator 也就是 TalentTree,主要负责解析、生成 url,头像,依赖等等 + - Skill 主要是 tips 部分。 + +而这一些都在一个 JS 里,对于一个库来说,是一件好事,但是对于一个项目来说,并非如此。 + +依赖的库有 + + - jQuery + - Knockout + +好在 Knockout 可以用 Require.js 进行管理,于是,使用了 ``Require.js`` 进行管理: + +```html + +``` + +``main.js`` 配置如下: + +```javascript +require.config({ + baseUrl: 'app', + paths:{ + jquery: 'lib/jquery', + json: 'lib/json', + text: 'lib/text' + } +}); + +require(['scripts/ko-bindings']); + +require(['lib/knockout', 'scripts/TalentTree', 'json!data/web.json'], function(ko, TalentTree, TalentData) { + 'use strict'; + var vm = new TalentTree(TalentData); + ko.applyBindings(vm); +}); +``` + +text、JSON 插件主要是用于处理 web.json,即用 JSON 来处理技能,于是不同的类到了不同的 JS 文件。 + + . + |____Book.js + |____Doc.js + |____ko-bindings.js + |____Link.js + |____main.js + |____Skill.js + |____TalentTree.js + |____Utils.js + +加上了后来的推荐阅读书籍等等。而 Book 和 Link 都是继承自 Doc。 + +```javascript +define(['scripts/Doc'], function(Doc) { + 'use strict'; + function Book(_e) { + Doc.apply(this, arguments); + } + Book.prototype = new Doc(); + + return Book; +}); +``` + +而这里便是后面对其进行重构的内容。Doc 类则是 Skillock 中类的一个缩影 + +```javascript +define([], function() { + 'use strict'; + var Doc = function (_e) { + var e = _e || {}; + var self = this; + + self.label = e.label || (e.url || 'Learn more'); + self.url = e.url || 'javascript:void(0)'; + }; + + return Doc; +}); +``` + +或者说这是一个 AMD 的 Class 应该有的样子。考虑到 this 的隐性绑定,作者用了self=this 来避免这个问题。最后 Return 了这个对象,我们在调用的就需要 new 一个。大部分在代码中返回的都是对象,除了在 Utils 类里面返回的是函数: + +```javascript +return { + getSkillsByHash: getSkillsByHash, + getSkillById: getSkillById, + prettyJoin: prettyJoin +}; +``` + +当然函数也是一个对象。 + +### 自动化测试 + +一直习惯用 Travis CI,于是也继续用 Travis Ci,``.travis.yml`` 配置如下所示: + +```yml +language: node_js +node_js: + - "0.10" + +notifications: + email: false + +branches: + only: + - gh-pages +``` + +使用 gh-pages 的原因是,我们一 push 代码的时候,就可以自动测试、部署等等,好处一堆堆的。 + +接着我们需要在 ``package.json`` 里面添加脚本 + +```javascript +"scripts": { + "test": "mocha" + } +``` + +这样当我们 push 代码的时候便会自动跑所有的测试。因为 mocha 的主要配置是用 ``mocha.opts``,所以我们还需要配置一下 ``mocha.opts`` + + --reporter spec + --ui bdd + --growl + --colors + test/spec + +最后的 ``test/spec`` 是指定测试的目录。 + +### JSLint + +> JSLint定义了一组编码约定,这比ECMA定义的语言更为严格。这些编码约定汲取了多年来的丰富编码经验,并以一条年代久远的编程原则 作为宗旨:能做并不意味着应该做。JSLint会对它认为有的编码实践加标志,另外还会指出哪些是明显的错误,从而促使你养成好的 JavaScript编码习惯。 + +当我们的 JS 写得不合理的时候,这时测试就无法通过: + + line 5 col 25 A constructor name should start with an uppercase letter. + line 21 col 62 Strings must use singlequote. + +这是一种驱动写出更规范 JS 的方法。 + + +### Mocha + +> Mocha 是一个优秀的JS测试框架,支持TDD/BDD,结合 should.js/expect/chai/better-assert,能轻松构建各种风格的测试用例。 + +最后的效果如下所示: + + Book,Link + Book Test + ✓ should return book label & url + Link Test + ✓ should return link label & url + +### 测试示例 + +简单地看一下 Book 的测试: + +```javascript +/* global describe, it */ + +var requirejs = require("requirejs"); +var assert = require("assert"); +var should = require("should"); +requirejs.config({ + baseUrl: 'app/', + nodeRequire: require +}); + +describe('Book,Link', function () { + var Book, Link; + before(function (done) { + requirejs(['scripts/Book'、], function (Book_Class) { + Book = Book_Class; + done(); + }); + }); + + describe('Book Test', function () { + it('should return book label & url', function () { + var book_name = 'Head First HTML与CSS'; + var url = 'http://www.phodal.com'; + var books = { + label: book_name, + url: url + }; + + var _book = new Book(books); + _book.label.should.equal(book_name); + _book.url.should.equal(url); + }); + }); +}); +``` + +因为我们用 ``require.js`` 来管理浏览器端,在后台写测试来测试的时候,我们也需要用他来管理我们的依赖,这也就是为什么这个测试这么长的原因,多数情况下一个测试类似于这样子的。(用 Jasmine 似乎会是一个更好的主意,但是用习惯 Jasmine 了) + +```javascript +describe('Book Test', function () { +it('should return book label & url', function () { + var book_name = 'Head First HTML与CSS'; + var url = 'http://www.phodal.com'; + var books = { + label: book_name, + url: url + }; + + var _book = new Book(books); + _book.label.should.equal(book_name); + _book.url.should.equal(url); +}); +}); +``` + +最后的断言,也算是测试的核心,保证测试是有用的。 + +## 代码质量与重构 + + - 当你写了一大堆代码,你没有意识到里面有一大堆重复。 + - 当你写了一大堆测试,却不知道覆盖率有多少。 + +这就是个问题了,于是偶然间看到了一个叫 code climate 的网站。 + +### Code Climate + +> Code Climate consolidates the results from a suite of static analysis tools into a single, real-time report, giving your team the information it needs to identify hotspots, evaluate new approaches, and improve code quality. + +Code Climate 整合一组静态分析工具的结果到一个单一的,实时的报告,让您的团队需要识别热点,探讨新的方法,提高代码质量的信息。 + +简单地来说: + +- 对我们的代码评分 +- 找出代码中的坏味道 + +于是,我们先来了个例子 + +Rating | Name | Complexity | Duplication | Churn | C/M | Coverage | Smells +--------|------|--------------|-------------|----------|---------|--------------------- +A | lib/coap/coap_request_handler.js | 24 | 0 | 6 | 2.6 | 46.4% | 0 +A | lib/coap/coap_result_helper.js | 14 | 0 | 2 | 3.4 | 80.0% | 0 +A | lib/coap/coap_server.js | 16 | 0 | 5 | 5.2 | 44.0% | 0 +A | lib/database/db_factory.js | 8 | 0 | 3 | 3.8 | 92.3% | 0 +A | lib/database/iot_db.js | 7 | 0 | 6 | 1.0 | 58.8% | 0 +A | lib/database/mongodb_helper.js | 63 | 0 | 11 | 4.5 | 35.0% | 0 +C | lib/database/sqlite_helper.js | 32 | 86 | 10 | 4.5 | 35.0% | 2 +B | lib/rest/rest_helper.js | 19 | 62 | 3 | 4.7 | 37.5% | 2 +A | lib/rest/rest_server.js | 17 | 0 | 2 | 8.6 | 88.9% | 0 +A | lib/url_handler.js | 9 | 0 | 5 | 2.2 | 94.1% | 0 + +分享得到的最后的结果是: + +![Coverage][1] + +### 代码的坏味道 + +于是我们就打开 ``lib/database/sqlite_helper.js``,因为其中有两个坏味道 + +Similar code found in two :expression_statement nodes (mass = 86) + +在代码的 ``lib/database/sqlite_helper.js:58…61 < >`` + +```javascript + SQLiteHelper.prototype.deleteData = function (url, callback) { + 'use strict'; + var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + SQLiteHelper.prototype.basic(sql_command, callback); +``` + +lib/database/sqlite_helper.js:64…67 < > + +与 + +```javascript +SQLiteHelper.prototype.getData = function (url, callback) { + 'use strict'; + var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + SQLiteHelper.prototype.basic(sql_command, callback); +``` + +只是这是之前修改过的重复。。 + +原来的代码是这样的 + +```javascript +SQLiteHelper.prototype.postData = function (block, callback) { + 'use strict'; + var db = new sqlite3.Database(config.db_name); + var str = this.parseData(config.keys); + var string = this.parseData(block); + + var sql_command = "insert or replace into " + config.table_name + " (" + str + ") VALUES (" + string + ");"; + db.all(sql_command, function (err) { + SQLiteHelper.prototype.errorHandler(err); + db.close(); + callback(); + }); +}; + +SQLiteHelper.prototype.deleteData = function (url, callback) { + 'use strict'; + var db = new sqlite3.Database(config.db_name); + var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + db.all(sql_command, function (err) { + SQLiteHelper.prototype.errorHandler(err); + db.close(); + callback(); + }); +}; + +SQLiteHelper.prototype.getData = function (url, callback) { + 'use strict'; + var db = new sqlite3.Database(config.db_name); + var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + db.all(sql_command, function (err, rows) { + SQLiteHelper.prototype.errorHandler(err); + db.close(); + callback(JSON.stringify(rows)); + }); +}; +``` +说的也是大量的重复,重构完的代码 + +```javascript +SQLiteHelper.prototype.basic = function(sql, db_callback){ + 'use strict'; + var db = new sqlite3.Database(config.db_name); + db.all(sql, function (err, rows) { + SQLiteHelper.prototype.errorHandler(err); + db.close(); + db_callback(JSON.stringify(rows)); + }); + +}; + +SQLiteHelper.prototype.postData = function (block, callback) { + 'use strict'; + var str = this.parseData(config.keys); + var string = this.parseData(block); + + var sql_command = "insert or replace into " + config.table_name + " (" + str + ") VALUES (" + string + ");"; + SQLiteHelper.prototype.basic(sql_command, callback); +}; + +SQLiteHelper.prototype.deleteData = function (url, callback) { + 'use strict'; + var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + SQLiteHelper.prototype.basic(sql_command, callback); +}; + +SQLiteHelper.prototype.getData = function (url, callback) { + 'use strict'; + var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url); + SQLiteHelper.prototype.basic(sql_command, callback); +}; +``` + +重构完后的代码比原来还长,这似乎是个问题~~ + +Git 提交信息及几种不同的规范 +=== + +> 受 Growth 3.0 开发的影响,最近更新文章的频率会有所降低。今天,让我们来谈谈一个好的 Git、SVN 提交信息是怎样规范出来的。 + +在团队协作中,使用版本管理工具 Git、SVN 几乎都是这个行业的标准。当我们提交代码的时候,需要编写提交信息(commit message)。 + +而提交信息的主要用途是:**告诉这个项目的人,这次代码提交里做了些什么**。如,我更新了 React Native Elements 的版本,那么它就可以是:``[T] upgrade react native elements``。对应的我修改的代码就是:``package.json`` 和 ``yarn.lock`` 中的文件。一般来说,建议**小步提交**,即按自己的 Tasking 步骤来的提交,每一小步都有对应的提交信息。这样做的主要目的是:**防止一次修改中,修改过多的文件,导致后期修改、维护、撤销等等困难**。 + +而对于不同的团队来说,都会遵循一定的规范,本文主要会介绍以下几种写法: + + - 工作写法 + - 常规写法 + - 开源库写法 + +那么,先从我习惯的做法说起。 + +工作写法 +--- + +在我的第一个项目里,我们使用 Jira 作为看板工具,Bamboo 作为持续集成服务器,并采用结对编程的方式进行。 + +在 Jira 里每一个功能卡都有对应的卡号,而 Bamboo 支持使用 Jira 的任务卡号关联的功能。即在持续构建服务器上示例对应的任务卡号,即相应的提交人。 + +因此,这个时候我们的规范稍微有一些特别: + +``` +[任务卡号] xx & xx: do something +``` + +比如:``[PHODAL-0001] ladohp & phodal: update documents``,解释如下: + + - ``PHODAL-0001``,业务的任务卡号,它可以帮我们找到某个业务修改的原因,即点出相应 bug 的来源 + - ``ladohp & phodal`` ,结对编程的两个人的名字,后者(phodal)一般是写代码的人,出于礼貌就放在后面了。由于 Git 的提交人只显示一个,所以写上两个的名字。当提交的人不在时,就可以问另外一个人修改的原因。 + - ``update documents``,我们做了什么事情 + +缺点:而对于采用看板的团队来说,并不存在任务卡号这种东西,因此就需要一种额外的作法。 + +常规写法 +--- + +对于我来说,我则习惯这种的写法: + +``` +[任务分类] 主要修改组件(可选):修改内容 +``` + +示例 1,``[T] tabs: add icons`` 。其中的 ``T`` 表示这是一个技术卡,``tabs`` 表示修改的是 Tabs,``add icons`` 则表示添加了图标。 + +示例 2,``[SkillTree] detail: add link data``。其中的 ``SkillTree`` 表示修改的是技能树 Tab 下的内容,``detail`` 则表示修改的是详情页,``add link data`` 则表示是添加了技能的数据 + +这样做的主要原因是,它可以轻松也帮我 **filter 出相应业务的内容**。 + +缺点:要这样做需要团队达到一致,因此付出一些额外的成本。 + +开源应用、开源库写法 +--- + +与我们日常工作稍有不同的是:工作中的 Release 计划一般都是事先安排好的,不需要一些 CHANGELOG 什么的。而开源应用、开源库需要有对应的 CHANGELOG,则添加了什么功能、修改了什么等等。毕竟有很多东西是由社区来维护的。 + +因此,这里以做得比较好的开源项目 Angular 为例展示。Angular 团队建议采用以下的形式: + +``` +(): + + + +