Repository: xirong/my-git Branch: master Commit: 5b7e2339baca Files: 11 Total size: 91.4 KB Directory structure: gitextract_9zbg0diq/ ├── command-handbook/ │ ├── git常用命令.xmind │ └── readme.md ├── git-workflow-tutorial.md ├── how-to-use-github.md ├── ixirong.com.md ├── readme.md ├── use-gitlab-github-together.md ├── useful-git-command.md ├── using-svn.md ├── video └── why-git.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: command-handbook/readme.md ================================================ 说明 ====== 目前收集的常用命令,包括[git-cheat-sheet.pdf](git-cheat-sheet.pdf) 和 [git常用命令.xmind](git常用命令.xmind) ,以后会持续更新 xmind 版本的命令,图片预览如下:  git常用命令 ----------------------  ================================================ FILE: git-workflow-tutorial.md ================================================ 说明: ====== 个人在学习`Git`工作流的过程中,从原有的 SVN 模式很难完全理解`Git`的协作模式,直到有一天我看到了下面的文章,好多遗留在心中的困惑迎刃而解: - 我们以使用SVN的工作流来使用`Git`有什么不妥? - `Git`方便的branch在哪里,团队多人如何协作?冲突了怎么办?如何进行发布控制? - 经典的master-发布、develop-主开发、hotfix-bug修复如何避免代码不经过验证上线? - 如何在`GitHub`上面与他人一起协作,star-fork-pull request是怎样的流程? 我个人很感激这篇文章,所以进行了整理,希望能帮到更多的人。整篇文章由 [xirong](https://github.com/xirong) 整理自 [oldratlee](https://github.com/oldratlee) 的`GitHub`,方便统一的学习回顾,在此感谢下面两位的贡献。 原文链接:[Git Workflows and Tutorials](https://www.atlassian.com/git/workflows) 简体中文:由 [oldratlee](https://github.com/oldratlee) 翻译在 `GitHub` 上 [`Git`工作流指南](https://github.com/oldratlee/translations/blob/master/git-workflows-and-tutorials/README.md) 在第三部分 企业日常开发模式探索,xirong 结合自己所在公司使用git的版本分支开发过程,进行了总结,欢迎大家提出更好的建议。 在第四部分 开发工作流的讨论 中,引用了几篇文章,包括 Github 的开发流程以及 Thoughtworkers 工程师发表的「Gitflow 有害论」,旨在表名流程并不是唯一的,适合自己当前团队的才是最好的。 --------------
# 一、译序 这篇指南以大家在`SVN`中已经广为熟悉使用的集中式工作流作为起点,循序渐进地演进到其它高效的分布式工作流,还介绍了如何配合使用便利的`Pull Request`功能,系统地讲解了各种工作流的应用。 如果你`Git`用的还不多,可以从前面的讲的工作流开始操练。在操作过程中去感受指南的讲解:解决什么问题、如何解决问题,这样理解就深了,也方便活用。 行文中实践原则和操作示例并重,对于`Git`的资深玩家可以梳理思考提升,而新接触的同学,也可以跟着step-by-step操练学习并在实际工作中上手使用。 工作流其实不是一个初级主题,背后的本质问题是 有效的项目流程管理 和 高效的开发协同约定,而不仅仅是`Git`或`SVN`等[`VCS`](http://zh.wikipedia.org/wiki/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6)或[`SCM`](http://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86)工具的使用。 关于`Git`工作流主题,网上体系的中文资料不多,主要是零散的操作说明,希望这篇文章能让你更深入理解并在工作中灵活有效地使用起来。 `Gitflow`工作流是经典模型,处于核心位置,体现了工作流的经验和精髓。随着项目过程复杂化,你会感受到这个工作流中的深思熟虑和威力! `Forking`工作流是分布式协作的(`GitHub`风格)可以先看看`GitHub`的Help:[Fork A Repo](https://help.github.com/articles/fork-a-repo/)和[Using pull requests](https://help.github.com/articles/using-pull-requests/) 。照着操作,给一个`GitHub`项目贡献你的提交,有操作经验再看指南容易意会。指南中给了[自己实现`Fork`的方法](https://github.com/oldratlee/translations/blob/master/git-workflows-and-tutorials/workflow-forking.md#%E5%BC%80%E5%8F%91%E8%80%85fork%E6%AD%A3%E5%BC%8F%E4%BB%93%E5%BA%93):`Fork`就是服务端的克隆。在指南的操练中使用代码托管服务(如`GitHub`、`Bitbucket`),可以点一下按钮就让开发者完成仓库的`fork`操作。 **_PS_**: 文中`Pull Request`的介绍用的是`Bitbucket`代码托管服务,由于和`GitHub`基本一样,如果你用的是`GitHub`(我自己也主要使用`GitHub`托管代码),不影响理解和操作。 **_PPS_**: 更多`Git`学习资料参见 - [`Git`的资料整理](https://github.com/xirong/my-git) by [@xirong](https://github.com/xirong) - 自己整理的分享PPT [`Git`使用与实践](https://github.com/oldratlee/software-practice-miscellany/blob/master/git/git-gitlab-usage.pptx) @ [个人整理一些`Git`](https://github.com/oldratlee/software-practice-miscellany/tree/master/git) ---------------- - :see_no_evil: [自己](http://weibo.com/oldratlee)理解粗浅,翻译中不足和不对之处,欢迎 :clap: - 建议,[提交`Issue`](https://github.com/oldratlee/translations/issues/new) - 指正,[`Fork`后提通过`Pull Requst`贡献修改](https://github.com/oldratlee/translations/fork) - 如有文章理解上有疑问 或是 使用过程中碰到些疑惑,请随时:raised_hands:[提交`Issue`](https://github.com/oldratlee/translations/issues/new) ,一起交流学习讨论! ---------------- # 二、`Git`工作流指南 :point_right: 工作流有各式各样的用法,但也正因此使得在实际工作中如何上手使用变得很头大。这篇指南通过总览公司团队中最常用的几种`Git`工作流让大家可以上手使用。 在阅读的过程中请记住,本文中的几种工作流是作为方案指导而不是条例规定。在展示了各种工作流可能的用法后,你可以从不同的工作流中挑选或揉合出一个满足你自己需求的工作流。  ## 2.1 集中式工作流 如果你的开发团队成员已经很熟悉`Subversion`,集中式工作流让你无需去适应一个全新流程就可以体验`Git`带来的收益。这个工作流也可以作为向更`Git`风格工作流迁移的友好过渡。  转到分布式版本控制系统看起来像个令人生畏的任务,但不改变已用的工作流,你也可以用上`Git`带来的收益。团队可以用和`Subversion`完全不变的方式来开发项目。 但使用`Git`加强开发的工作流,相比`SVN`,`Git`有以下两个优势: 首先,每个开发者可以有属于自己的整个工程的本地拷贝。隔离的环境让各个开发者的工作和项目的其他部分修改独立开来 —— 即自由地提交到自己的本地仓库,先完全忽略上游的开发,直到方便的时候再把修改反馈上去。 其次,`Git`提供了强壮的分支和合并模型。不像`SVN`,`Git`的分支设计成可以做为一种用来在仓库之间集成代码和分享修改的『失败安全』的机制。 ### 2.1.1 工作方式 像`Subversion`一样,集中式工作流以中央仓库作为项目所有修改的单点实体。相比`SVN`缺省的开发分支`trunk`,`Git`叫做`master`,所有修改提交到这个分支上。本工作流只用到`master`这一个分支。 首先,开发者克隆中央仓库。在自己的项目拷贝中,像`SVN`一样的编辑文件和提交修改;但修改是存在本地的,和中央仓库是完全隔离的。开发者可以把和上游的同步延后到一个方便时间点。 然后,开发者发布修改到正式项目中,开发者要把本地`master`分支的修改『推』到中央仓库中。这相当于`svn commit`操作,但`push`操作会把所有还不在中央仓库的本地提交都推上去。  ### 2.1.2 冲突解决 中央仓库代表了正式项目,所以提交历史应该被尊重且是稳定不变的。如果开发者本地的提交历史和中央仓库有分歧,`Git`会拒绝`push`提交否则会覆盖已经在中央库的正式提交。  在开发者提交自己功能修改到中央库前,需要先`fetch`在中央库的新增提交,`rebase`自己提交到中央库提交历史之上。 这样做的意思是在说,『我要把自己的修改加到别人已经完成的修改上。』最终的结果是一个完美的线性历史,就像以前的`SVN`的工作流中一样。 如果本地修改和上游提交有冲突,`Git`会暂停`rebase`过程,给你手动解决冲突的机会。`Git`解决合并冲突,用和生成提交一样的[`git status`](https://www.atlassian.com/git/tutorial/git-basics#!status)和[`git add`](https://www.atlassian.com/git/tutorial/git-basics#!add)命令,很一致方便。还有一点,如果解决冲突时遇到麻烦,`Git`可以很简单中止整个`rebase`操作,重来一次(或者让别人来帮助解决)。 ### 2.1.3 示例 让我们一起逐步分解来看看一个常见的小团队如何用这个工作流来协作的。有两个开发者小明和小红,看他们是如何开发自己的功能并提交到中央仓库上的。 #### 有人先初始化好中央仓库  第一步,有人在服务器上创建好中央仓库。如果是新项目,你可以初始化一个空仓库;否则你要导入已有的`Git`或`SVN`仓库。 中央仓库应该是个裸仓库(`bare repository`),即没有工作目录(`working directory`)的仓库。可以用下面的命令创建: ```bash ssh user@host git init --bare /path/to/repo.git ``` 确保写上有效的`user`(`SSH`的用户名),`host`(服务器的域名或IP地址),`/path/to/repo.git`(你想存放仓库的位置)。 注意,为了表示是一个裸仓库,按照约定加上`.git`扩展名到仓库名上。 #### 所有人克隆中央仓库  下一步,各个开发者创建整个项目的本地拷贝。通过[`git clone`](https://www.atlassian.com/git/tutorial/git-basics#!clone)命令完成: ```bash git clone ssh://user@host/path/to/repo.git ``` 基于你后续会持续和克隆的仓库做交互的假设,克隆仓库时`Git`会自动添加远程别名`origin`指回『父』仓库。 #### 小明开发功能  在小明的本地仓库中,他使用标准的`Git`过程开发功能:编辑、暂存(`Stage`)和提交。 如果你不熟悉暂存区(`Staging Area`),这里说明一下:**暂存区**用来准备一个提交,但可以不用把工作目录中所有的修改内容都包含进来。 这样你可以创建一个高度聚焦的提交,尽管你本地修改很多内容。 ```bash git status # 查看本地仓库的修改状态 git add # 暂存文件 git commit # 提交文件 ``` 请记住,因为这些命令生成的是本地提交,小明可以按自己需求反复操作多次,而不用担心中央仓库上有了什么操作。 对需要多个更简单更原子分块的大功能,这个做法是很有用的。 #### 小红开发功能  与此同时,小红在自己的本地仓库中用相同的编辑、暂存和提交过程开发功能。和小明一样,她也不关心中央仓库有没有新提交; 当然更不关心小明在他的本地仓库中的操作,因为所有本地仓库都是私有的。 #### 小明发布功能  一旦小明完成了他的功能开发,会发布他的本地提交到中央仓库中,这样其它团队成员可以看到他的修改。他可以用下面的[`git push`命令](https://www.atlassian.com/git/tutorial/remote-repositories#!push): ```bash git push origin master ``` 注意,`origin`是在小明克隆仓库时`Git`创建的远程中央仓库别名。`master`参数告诉`Git`推送的分支。 由于中央仓库自从小明克隆以来还没有被更新过,所以`push`操作不会有冲突,成功完成。 #### 小红试着发布功能  一起来看看在小明发布修改后,小红`push`修改会怎么样?她使用完全一样的`push`命令: ```bash git push origin master ``` 但她的本地历史已经和中央仓库有分岐了,`Git`拒绝操作并给出下面很长的出错消息: ``` error: failed to push some refs to '/path/to/repo.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') hint: before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` 这避免了小红覆写正式的提交。她要先`pull`小明的更新到她的本地仓库合并上她的本地修改后,再重试。 #### 小红在小明的提交之上`rebase`  小红用[`git pull`](https://www.atlassian.com/git/tutorial/remote-repositories#!pull)合并上游的修改到自己的仓库中。 这条命令类似`svn update`——拉取所有上游提交命令到小红的本地仓库,并尝试和她的本地修改合并: ```bash git pull --rebase origin master ``` `--rebase`选项告诉`Git`把小红的提交移到同步了中央仓库修改后的`master`分支的顶部,如下图所示:  如果你忘加了这个选项,`pull`操作仍然可以完成,但每次`pull`操作要同步中央仓库中别人修改时,提交历史会以一个多余的『合并提交』结尾。 对于集中式工作流,最好是使用`rebase`而不是生成一个合并提交。 #### 小红解决合并冲突  `rebase`操作过程是把本地提交一次一个地迁移到更新了的中央仓库`master`分支之上。 这意味着可能要解决在迁移某个提交时出现的合并冲突,而不是解决包含了所有提交的大型合并时所出现的冲突。 这样的方式让你尽可能保持每个提交的聚焦和项目历史的整洁。反过来,简化了哪里引入`Bug`的分析,如果有必要,回滚修改也可以做到对项目影响最小。 如果小红和小明的功能是不相关的,不大可能在`rebase`过程中有冲突。如果有,`Git`在合并有冲突的提交处暂停`rebase`过程,输出下面的信息并带上相关的指令: ``` CONFLICT (content): Merge conflict in| Author: | Jiang Xin |
|---|---|
| Version: | v0.9.1-13-g5075479 |
| Copyright: | Creative Commons BY-NC-SA |
动笔写GitHub不是因为我对其了解,恰恰是对其太不了解。
在我的《Git权威指南》 [1] 一书中,涉及到GitHub的只有区区三页纸,这显然回答不了读者对于GitHub的诸多疑问。 记得在《Git权威指南》刚刚完稿之际,机械工业出版社华章公司的杨福川编辑就鼓动我写一本关于GitHub的书,我用了好多理由推辞了。 头条理由就是我真的累着了。在每一章节开始动笔之时,都好像是坐在了中学语文考试的考堂上写作文,时间快到了可仍然动不了笔, 再写一本书无疑要重复这一痛苦的经历。 第二个理由是我更喜欢编程,而不是写文档,尤其写GitHub会有大量截图、图像处理的琐碎工作。 第三个理由彻底让编辑投降,那就是GitHub是一个国外网站,也许书一出,【此句已被原作者删除】。
让我最终决定动笔,是源于CSDN蒋总在美国拜访GitHub总部后告诉我的一些见闻,我对GitHub如此成功运作产生了兴趣,于是开始研究GitHub的博客,愈发发现GitHub是一群有趣的人在做的有趣的事,如果只把GitHub当作一个Git服务器,实在是暴殄天物。GitHub已经并将继续获得成功,若真能凭借此书把GitHub尽量全面地展现,让每一个Git使用者用好GitHub也是一件幸事。
这本书将采用GitHub的方式进行撰写和发布 [2] ,任何人都可以看到本书(包括源码),更可以用GitHub的方法参与本书的撰写和纠错。网络出版对于我和杨福川编辑都是一个全新的体验。感谢Git,让我在一年内拥有了两种不同的出版体验。
– 蒋鑫, 2011.12
| [1] | http://www.worldhello.net/gotgit/ |
| [2] | https://github.com/gotgit/gotgithub |
术语用图片的方式进行讲解,很容易就懂了
- [图文并茂-猴子都能懂的git入门教程](http://backlogtool.com/git-guide/cn/) 全面,生动形象,图文并茂,简单易懂,强烈推荐!
关于日常中使用git来版本管理的流程写的很不错的一本书,日常工作模式、流程怎样更合理的工作!
** 最后,当你开始使用git的时候,学会用终端,比如你想看关于branch,那么大胆的时候 *git branch --help * 查看相应的命令! **
================================================
FILE: readme.md
================================================
# 说明
这整个 Repository 是关于分布式版本管理工具 Git 及托管商 Github 的使用,大部分都是网友写的内容,在这里只是做一个资源的汇总和合理的安排,希望能成为最好的学习 Git 的资源,从开始入门使用,到慢慢的提高,再到理解各种原理,希望能够达成这个目标。
网络上面已经有了那么多的关于 Git 的文章,为什么还要弄一个repo来专门记录?网上的文章都是片面的,稍微全点的讲解的不够全面、深入,没能满足我对于文章的想象,所以决定自己来写。
如果你要有一些资源,希望和我一起,把这个搞起来,很简单,`Fork-修改- Pull Request` 就 ok。
# 新手入门
- [为什么开始使用 Git 版本管理,Git VS Svn 有哪些区别?](https://github.com/xirong/my-git/blob/master/why-git.md)
- [开篇:一篇适合入门学习git的资料汇总](https://github.com/xirong/my-git/blob/master/ixirong.com.md) 本人的拙笔,欢迎吐槽!
- [Github-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet) 关于使用 Git 和 Github 的一些技巧汇总,中文版在此[GitHub秘籍](https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md)
- [Git for beginners: The definitive practical guide - from stackoverflow.com](http://stackoverflow.com/questions/315911/git-for-beginners-the-definitive-practical-guide?rq=1) It's so useful to a beginner ,just open the url , read and practice .
- [Visual Git Cheat Sheet](http://ndpsoftware.com/git-cheatsheet.html) 通过 Git 的几个工作区 Stash、Workspace、Index、Local Repository、Upstream Repository 来汇总日常使用的 Git 命令,备忘推荐。
# Git 客户端
Mac 和 Linux 系统推荐使用终端即可,Git 一开始的命令的确很多,别无它法,熟能生巧,多练习即可能够掌握日常使用的一些命令,再配合[`常用命令的alias`](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases)或者强大的 [`zsh 终端`](http://www.ixirong.com/2015/04/27/strong-bash-use-oh-my-zsh/)都能显著的提升效率,当然如果非得寻找图形化客户端,也不是没有;Windows下还是尽快熟悉客户端的使用吧,因为win下面的bash太难用了:
- [GUI Clients](https://git-scm.com/downloads/guis) 官方推荐图形客户端,罗列的包括了Mac、Windows、Linux下的客户端,免费及付费的都有,你可以在这里面挑选一个就ok。
- [Git for windows](https://msysgit.github.io/) 针对 Window 系统发布的客户端,集成了 Shell 窗口,方便在 Win 下面使用命令操作。
- [TortoiseGit - The coolest Interface to Git Version Control](https://code.google.com/p/tortoisegit/) 在window下使用git,那就不得不提“乌龟”,安装了 Tortoise 后,右键图形化操作根本分辨不出来哪是 Git,哪是 Svn,很方便使用 Svn 的用户过度过来。
- [Tower2](http://www.git-tower.com/) 号称最好的 Git 客户端,只有 Mac 版本,收费,集成 Github、Gitlab、Xcode等服务。
- [SourceTree](https://www.sourcetreeapp.com/) 免费,功能齐全,Mac+Window 版本,集成 Github 等服务。
- [SmartGit](http://www.syntevo.com/smartgit/) 非商业用途免费,全平台支持,集成 Github服务。内置 SSH client ,文件比较与合并工具。
- [Fork](https://git-fork.com) 免费,Mac+Window 版本,功能齐全,轻便流畅。
# Git branch
- [A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) 介绍日常推荐的分支开发模型,基于此模型可以通过这个小游戏来进行学习 [Learn Git Branch](http://pcottle.github.io/learnGitBranching/)
- [Git工作流指南](https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md)完整的对比目前使用的集中式(Svn)工作流、功能分支工作流、Gitflow 工作流、Forking 工作流、Pull Request 等几种不同的模式,通俗易懂,强烈推荐看一看,如果觉的排版不好,请查看原分页文章 [Git-workflow-translations](https://github.com/oldratlee/translations/tree/master/git-workflows-and-tutorials)
- 熟悉的工作流后,你是否也想要在 Github 上与他人一起协同工作?那么问题来了,[Github全程指南-如何高效使用?](how-to-use-github.md)
- [Understanding the GitHub Flow](https://guides.github.com/introduction/flow/index.html) This guide explains how and why GitHub Flow works 简单实用,更好的理解Github的模式。
- [Github 协同开发流程](http://www.ruanyifeng.com/blog/2015/08/git-use-process.html) 图片很赞,简洁易懂。
# Git expert
- 项目依赖其他项目,比如公共 Css、Dll 等等,强大的 Git-submodule 优雅的解决这类问题。理解阅读 [Git Tools - Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) ,备忘或者查看命令阅读 [Git Submodule Tutorial](https://git.wiki.kernel.org/index.php/GitSubmoduleTutorial) 或者 [Git Submodule 使用完整教程](http://www.kafeitu.me/git/2012/03/27/git-submodule.html)
- [Git Submodule 的一些注意事项](http://blog.devtang.com/blog/2013/05/08/git-submodule-issues/) 一些需要理解并注意的操作
# Git 书籍
- [Pro Git](http://git-scm.com/book/zh/v1) 作者Scott Chacon是 Github 的员工,Git 的布道者,这本书被誉为 Git 学习圣经,中间有好多插图描述的浅显易懂,挺适合详细学习下的,最新英文第二版《[Pro Git (Editon 2)](http://git-scm.com/book/en/v2)》;
- [Git-internals-pdf](https://github.com/pluralsight/git-internals-pdf) 老外写的,很给力,从目录上面包括安装使用以及设计原理都有讲解,有机会看看。Pdf 电子版本直接下载地址 [Git-internals.pdf](ebooks/git-internals.pdf)
- [Git Community Book](http://gitbook.liuhui998.com/) 汇聚了 Git 社区的很多精华, 并对 Git 的对象模型原理等做了解释,可以深入的了解下 Git 原理。pdf电子版本直接下载地址 [Git Community Book.pdf](ebooks/Git Community Book.pdf)
- [Git权威指南](http://book.douban.com/subject/6526452/) 国内版本控制咨询顾问蒋鑫先生的原创书籍,原生中文叙述,更容易理解,查看[作者写书的缘由](http://www.worldhello.net/gotgit/)
- [Git Reference](http://gitref.org/) [中文](http://gitref.org/zh/index.html) 为学习与记忆 Git 使用中最重要、最普遍的命令提供快速翻阅,可作为参考资料。
- [Git Magic - a guide from standord](https://github.com/blynn/gitmagic) 斯坦福大学Git学习指南,适合快速入门。
# Git 效率提升
- [Git flow 工具](https://github.com/petervanderdoes/gitflow)
- [Git flow 中文备忘清单](http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html)
- 一个很有意思的学习 Git 的小游戏 http://pcottle.github.io/learnGitBranching/
- [Git completion](https://github.com/git/git/tree/master/contrib/completion) 终端 Git 命令的 Tab 键补全功能,比如打开终端,输入`git che`,按 Tab 键,则会出现`check-attr\check-ignore\checkout`等等的选项,支持 Bash、Zsh 等 Shell,使用方法(以 Bash Shell 为例):下载链接中相应的版本到用户目录下,修改`~/.bashrc`文件 ,加入`source ~/git-completion.bash` ,使得每次打开终端时都执行一次`git-completion.bash`脚本,来完成git 命令的 Tab 补全。或者采用这种方法[Quick Tip: Autocomplete Git Commands and Branch Names in Bash](http://code-worrier.com/blog/autocomplete-git/)
- [.gitignore template](https://github.com/github/gitignore) 各种语言、各种编辑器的`.gitignore`文件模板,当你进行某些语言的开发时候,直接使用相应的模板即可,省去自己写的时间(还不全),当然你也可以去贡献自己的模板,不知道`.gitignore`? 简单讲就是不让git跟踪某些文件,详情阅读:http://git-scm.com/docs/gitignore
**PS:** 推荐使用 `.gitignore_global` 文件进行全局过滤,比如mac下的 `.DS_Store` 文件,省去在每个 Repo 下进行设置 `.gitignore`文件了。全局模板参考:https://github.com/github/gitignore/tree/master/Global
# Git extensions
- Git 的大文件支持[Git LFS](https://github.com/github/git-lfs) : Git在对大文件进行版本管理的时候,速度上是很慢的,一个帮助处理大文件的扩展插件,在 GithubHelp [Working with large files](https://help.github.com/articles/working-with-large-files/) 中提到,不建议对大文件如日志、database等使用Git进行版本控制,如果非要有这种需求,则建议使用 Git LFS 。
# 实践备忘
- 常用命令手册 [Git 日常开发常用命令整理](useful-git-command.md),日常开发中的利器,可以当做备忘录来使用,推荐👍。
- 总是使用 `git merge --no-ff` 而不是 `git merge` ,记录下分支的变更历史。 详情 http://stackoverflow.com/questions/9069061/what-is-the-difference-between-git-merge-and-git-merge-no-ff
- 恰当的使用 `git pull --rebase` 避免不必要的merge记录。 详情 http://stackoverflow.com/questions/2472254/when-should-i-use-git-pull-rebase 「You should use `git pull --rebase` when your changes do not deserve a separate branch」
- [Git-flight-rules](https://github.com/k88hudson/git-flight-rules) 一些日常使用中的场景,比如提交错了分支、提交时的用户名邮箱不对、丢弃某些提交、未提交的代码直接提交到另外一个分支等等,很实用。
- [How to undo (almost) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) 撤销一切,汇总各种回滚撤销的场景,加强学习。
- [怎样在一台电脑上同时使用公司 GitLab 和 Github 的服务?](use-gitlab-github-together.md) 由于公司团队使用 GitLab 来托管代码,同时,个人在 Github 上还有一些代码仓库,可公司邮箱与个人邮箱是不同的,由此产生的 SSH key 也是不同的,这就造成了冲突 ,文章提供此类问题的解决方案。
- [如何书写提交信息](http://chris.beams.io/posts/git-commit/) 当项目越来越大,提交信息越来越复杂的时候,如何书写好提交信息就变得至关重要,这篇文章的作者总结出7条准则。
- [Commit message 和 change log编写规范-阮一峰](http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html) 良好的 commit log 好处大大的多。 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w)
- [git-recipes](https://github.com/geeeeeeeeek/git-recipes/wiki) @童仲毅 整理翻译的一些优秀文章。
- [githug](https://github.com/Gazler/githug) Git your game on. 使用通关游戏的形式来练习git的一些命令,非常有趣。
================================================
FILE: use-gitlab-github-together.md
================================================
说明
====================
由于公司团队使用 GitLab 来托管代码,同时,个人在 Github 上还有一些代码仓库,可公司邮箱与个人邮箱是不同的,由此产生的 SSH key 也是不同的,这就造成了冲突 ,文章提供此类问题的解决方案:**如何在一台机器上面同时使用 Github 与 Gitlab 的服务?**
# 问题产生场景
-------------
## 无密码与远程服务器交互的秘密 - SSH
如果采用`ssh 协议`或者`git 协议`通过终端命令对远程仓库进行`push`操作的时候,大概的过程如下:(前提在 Github 上已经配置的本机的 SSH Public Key)
1. 客户端发起一个 Public Key 的认证请求,并发送RSA Key的模数作为标识符。(关于 RSA Key 详细 [维基百科](https://en.wikipedia.org/wiki/RSA_(algorithm)))
2. 服务端检查是否存在请求帐号的公钥(Linux中存储在~/.ssh/authorized_keys文件中),以及其拥有的访问权限。
3. 服务端使用对应的公钥对一个随机的256位的字符串进行加密,并发送给客户端。
4. 客户端使用私钥对字符串进行解密,并将其结合session id生成一个MD5值发送给服务端。 结合session id的目的是为了避免攻击者采用重放攻击(replay attack)。
5. 服务端采用同样的方式生成MD5值与客户端返回的MD5值进行比较,完成对客户端的认证。
6. 将push的内容进行加密与服务端传输数据。
关于 SSH,请查看 [SSH原理简介](http://erik-2-blog.logdown.com/posts/74081-ssh-principle) ,更通俗易懂的文章请查看[阮一峰-SSH原理与运用(一):远程登录](http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html) 。
## 具体场景
无论使用哪种代码托管服务商,对于 Git 而言,`邮箱` 是识别用户的唯一手段,所以对于不同的服务商,由于邮箱不同,那么通过邮件名创建的 SSH Key 自然是不同的,这时候在不同的服务商之间进行 `push` 命令的时候,Git 是不知道使用哪个 SSH Key ,自然导致 `push` 的失败。场景如下:
1. 在公司团队使用搭建的 Gitlab 服务,提交邮箱`xirong.liu@corp.xx.com`, 个人 Github 服务,提交邮箱 `ixirong.liu@gmail.com` (Bitbucket 同理)。
2. 有两个Github账户,不同的账户提交不同的仓库内容。
# 解决方案
## 方案一:同一个邮箱
由于`邮箱`是识别的唯一手段,那么自然的,这两者采用同一个邮箱,生成的 public key 也会是同一个,上传到 Github 或者 Gitlab 上面,在 Git 的配置中 ,设置好 Global 的配置 :` git config --global user.name 'xirong.liu' && git config --global user.email 'xirong.liu@corp.xx.com'` 进行日常的开发是没有问题的。
实际生活中采用同一个邮箱的可能性并不是太大,这就引出了方案二
## 方案二:基于config文件
所谓的方案二,原理上就是对 SSH 协议配置 config 文件,对不同的域名采用不同的认证密钥。
#### git config 介绍
Git有一个工具被称为git config,它允许你获得和设置配置变量;这些变量可以控制Git的外观和操作的各个方面。这些变量可以被存储在三个不同的位置:
1. /etc/gitconfig 文件:包含了适用于系统所有用户和所有库的值。如果你传递参数选项’`--system`’ 给 git config,它将明确的读和写这个文件。
2. ~/.gitconfig 文件 :具体到你的用户。你可以通过传递 ‘`--global`’ 选项使Git 读或写这个特定的文件。
3. 位于 Git 目录的 config 文件 (也就是 .git/config) :无论你当前在用的库是什么,特定指向该单一的库。每个级别重写前一个级别的值。因此,在 .git/config 中的值覆盖了在/etc/gitconfig中的同一个值,可以通过传递‘`--local`’选项使Git 读或写这个特定的文件。
由于采用了不同的邮箱,对不同的服务商进行提交,所以此时我们经常配置的 `git config --global` 就不能常用了,必须在每个仓库的目录下进行配置自己的用户名、邮箱。(嫌麻烦?xirong 是这么解决的,由于个人的 Github 上有较多的仓库,而自己团队的代码基本上都是稳定的,有数的几个,所以在 `git config --global user.email 'ixirong.liu@gmail.com'` 中全局配置的是个人邮箱,在团队的项目中配置)
### 1. 配置 Git 用户名、邮箱
如刚才所说,xirong 的配置如下:
``` bash
# 全局配置,Github仓库中默认使用此配置
git config --global user.name 'xirong' && git config --global user.email 'ixirong.liu@gmail.com'
# 团队项目配置,每次新创建一个项目,需要执行下
git config --local user.name 'xirong.liu' && git config --local user.email 'xirong.liu@corp.example.com'
```
### 2. 生成 ssh key 上传到 Github/Gitlab
ssh key 默认生成后保存在 `~/.ssh/`目录下 ,默认为 `id_rsa 和 id_rsa.pub` 两个文件,由于我们需要分开配置,所以这么做:
``` bash
# 生成公钥、密钥的同时指定文件名,Gitlab使用
ssh-keygen -t rsa -f ~/.ssh/id_rsa.gitlab -C "xirong.liu@corp.example.com"
# 生成默认,Github使用
ssh-keygen -t rsa -C "ixirong.liu@gmail.com"
```
命令执行完成后,这时`~/.ssh`目录下会多出`id_rsa.gitlab`和`id_rsa.gitlab.pub`两个文件,`id_rsa.gitlab.pub` 里保存的就是我们要使用的key,这个key就是用来上传到 Gitlab上的。
### 3. 配置 config 文件
在 `~/.ssh`目录下,如果不存在,则新建 `touch ~/.ssh/config`文件 ,文件内容添加如下:
``` bash
Host corp.example.com
HostName git.corp.example.com
IdentityFile ~/.ssh/id_rsa.gitlab
User xirong.liu
```
- `Host`参数是命令行给出的主机名,比如`ssh -T git@corp.example.com`,那么此时的主机(`Host`)就是`corp.example.com`
- 只有`Host`匹配之后,`SSH`把`git@corp.example.com`转换成`git.corp.example.com`
- `Host`不支持`*`和主机名混用,即`*.example.com`;单独`*`表示匹配所有主机,也就是默认规则
- `HostName`应该是必须填写的内容,根据你使用的命令行内容来填写
配置完成后,符合`git.corp.example.com`的 Git 仓库,均采取` ~/.ssh/id_rsa.gitlab` 密钥进行验证,其它的采取默认的。
### 4. 上传public key 到 Github/Gitlab
以Github为例,过程如下:
1. 登录github
2. 点击右上方的Accounting settings图标
3. 选择 SSH key
4. 点击 Add SSH key
在出现的界面中填写SSH key的名称,填一个你自己喜欢的名称即可,然后将上面拷贝的`~/.ssh/id_rsa.pub`文件内容粘帖到`key`一栏,在点击“`add key`”按钮就可以了。
添加过程github会提示你输入一次你的github密码 ,确认后即添加完毕。 上传Gitlab的过程一样,请自己操作。
### 5. 验证是否OK
由于每个托管商的仓库都有唯一的后缀,比如 Github的是 `git@github.com:*`,所以可以这样测试:
``` bash
➜ ~ ssh -T git@github.com
Hi xirong! You've successfully authenticated, but GitHub does not provide shell access.
➜ ~ ssh -T git@gitlab.dev
Welcome to GitLab, xirong.liu!
```
看到这些 `Welcome` 信息,说明就是 OK的了。
以后,如果还有任何的需求,都可以这么解决,看下 xirong 的几个托管仓库:
``` bash
➜ ~ ll ~/.ssh
total 40
-rw-r--r-- 1 xirong staff 264 Jul 10 14:42 config
-rw------- 1 xirong staff 3243 Jul 10 14:09 id_rsa
-rw------- 1 xirong staff 1675 Jan 28 20:39 id_rsa.gitlab
-rw-r--r-- 1 xirong staff 407 Jan 28 20:39 id_rsa.gitlab.pub
-rw-r--r-- 1 xirong staff 747 Jul 10 14:09 id_rsa.pub
-rw------- 1 xirong staff 1679 Jun 22 11:42 id_rsa_gitcafe
-rw-r--r-- 1 xirong staff 407 Jun 22 11:42 id_rsa_gitcafe.pub
-rw-r--r-- 1 xirong staff 9139 Jul 29 15:08 known_hosts
```
================================================
FILE: useful-git-command.md
================================================
说明
Git 常用、不常用、实用的命令,这些命令都是在日常使用过程中遇到过整理下来的,留作备忘,如果对这些命令还不明白什么意思,请参考学习:[Git 新手入门](https://github.com/xirong/my-git#新手入门) 。
在日常开发中,由于采用 Git 作为版本控制,经常跟命令行打交道,记录整理下使用到的一些命令,方便回顾。
[TOC]
# Concept
```
master : default development branch
origin : default upstream repository
HEAD : current branch and commit
HEAD^ : parent of HEAD
HEAD~4 : the great-great grandparent of HEAD
```
# Alias
下面的只是例子,想改成什么跟随自己的意愿即可。
``` bash
git config --global alias.st status //status 缩写成 st
git config --global alias.co checkout //checkout 缩写成 co
git config --global alias.br branch //branch 缩写成 br
git config --global alias.ci commit //commit 缩写成 ci
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
```
如果不想使用了,删除掉的话,直接删除 conf 配置文件中的行即可,global 的在当前用户下`vim ~/.gitconfig` 删除` alias`下你配置的内容接口;若是当前仓库则在 `.git/config` 中。
# Git Config
Git 配置文件分为三级,系统级(--system)、用户级(--global)和目录级(--local),三者的使用优先级以离目录 (repository)最近为原则,如果三者的配置不一样,则生效优先级 **目录级>用户级>系统级**,可以通过 `git config --help` 查看更多内容。
+ 系统级配置存储在 `/etc/gitconfig` 文件中,可以使用 `git config --system user.name "jim"` ,`git config --sytem user.email "jim.jim@gmail.com"` 来进行配置,该配置对系统上所有用户及他们所拥有的仓库都生效的配置值。
+ 用户级存储在每个用户的 `~/.gitconfig` 中,可以使用 `git config --global user.name "jim"` ,`git config --global user.email "jim.jim@gmail.com"` 来进行配置,该配置对当前用户上所有的仓库有效。
+ 目录级存储在每个仓库下的 `.git/config` 中,可以使用 `git config --local user.name "jim"` , `git config --local user.email "jim.jim@gmail.com"` 来进行配置,只对当前仓库生效。
# Basic Usage
- 添加文件到暂存区(staged):`git add filename` / `git stage filename`
- 将所有修改文件添加到暂存区(staged): `git add --all` / `git add -A`
- 提交修改到暂存区(staged):`git commit -m 'commit message'` / `git commit -a -m 'commit message'` 注意理解 -a 参数的意义
- 从Git仓库中删除文件:`git rm filename`
- 从Git仓库中删除文件,但本地文件保留:`git rm --cached filename`
- 重命名某个文件:`git mv filename newfilename` 或者直接修改完毕文件名 ,进行`git add -A && git commit -m 'commit message'` Git会自动识别是重命名了文件
- 获取远程最新代码到本地:`git pull (origin branchname)` 可以指定分支名,也可以忽略。pull 命令自动 fetch 远程代码并且 merge,如果有冲突,会显示在状态栏,需要手动处理。更推荐使用:`git fetch` 之后 `git merge --no-ff origin branchname` 拉取最新的代码到本地仓库,并手动 merge 。
# Repository
- 检出(clone)仓库代码:`git clone repository-url` / `git clone repository-url local-directoryname`
+ 例如,clone jquery 仓库到本地: `git clone git://github.com/jquery/jquery.git`
+ clone jquery 仓库到本地,并且重命名为 my-jquery :`git clone git://github.com/jquery/jquery.git my-jquery`
- 查看远程仓库:`git remote -v`
- 添加远程仓库:`git remote add [name] [repository-url]`
- 删除远程仓库:`git remote rm [name]`
- 修改远程仓库地址:`git remote set-url origin new-repository-url`
- 拉取远程仓库: `git pull [remoteName] [localBranchName]`
- 推送远程仓库: `git push [remoteName] [localBranchName]` 例: `git push -u orgin master ` 将当前分支推送到远端master分支
- 将本地 test 分支提交到远程 master 分支: `git push origin test:master` (把本地的某个分支 test 提交到远程仓库,并作为远程仓库的 master 分支) 提交本地 test 分支作为远程的 test 分支 :`git push origin test:test `
# Checkout
checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。
 
**匿名分支**:如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像 master~3 类似的东西,就得到一个匿名分支,称作 detached HEAD(被分离的 HEAD 标识)。

当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)一旦此后你切换到别的分支,比如说 master,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用 2eecb。详细查看:[visual-git-guide#detached](http://marklodato.github.io/visual-git-guide/index-zh-cn.html#detached)
但是,如果你想保存这个状态,可以用命令 `git checkout -b name` 来创建一个新的分支。

# Log
> Description : Shows the commit logs.
The command takes options applicable to the git rev-list command to control what is shown and how, and options applicable to the git diff-* commands to control how the changes each commit introduces are shown.
> git log [options] [revision range] [path]
常用命令整理如下:
- 查看日志:`git log`
- 查看日志,并查看每次的修改内容:`git log -p`
- 查看日志,并查看每次文件的简单修改状态:`git log --stat`
- 一行显示日志:`git log --pretty=oneline` / `git log --pretty='format:"%h - %an, %ar : %s'`
- 查看日志范围:
+ 查看最近10条日志:`git log -10`
+ 查看2周前:`git log --until=2week` 或者指定2周的明确日期,比如:`git log --until=2015-08-12`
+ 查看最近2周内:`git log --since=2week` 或者指定2周明确日志,比如:`git log --since=2015-08-12`
+ 只查看某个用户的提交:`git log --committer=user.name` / `git log --author=user.name`
+ 只查看提交msg中包含某个信息的历史,比如包含'测试'两个字的:`git log --grep '测试'`
+ 试试这个 : `git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit` 感觉好用就加成 alias ,方便日后用,方法:`git config --global alias.aliasname 'alias-content'`
+ 更多用法:[Viewing the History -- 《Pro Git2》](http://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)
`log` 的目的就是为了查看改动点来排查问题,除了 ` git log` 还可以使用 `git show` 、`git blame` 来查看文件的改动。
- Who changed what and when in a file : `git blame $file`
- 查看一次 commit 中修改了哪些文件: `git show --pretty="" --name-only