Git笔记
一、基本知识
Git是什么:
Git是一种版本控制工具,和SVN(集中式)不同的是,GIT是分布式的。此外,SVN采用增量式管理,即每次只保存更新的内容;而Git采取系统快照方式。
Git支持避免写冲突的(并行不悖的)数据备份、版本管理、权限控制、分支管理。
Git所提供的权限控制相比SVN而言更basic,并且可以接受团队外开发者所贡献的代码,审核后即可加入项目中来,SVN不提供该功能。集中式的版本控制将数据存储在服务器上,容易产生“单点故障”的问题。
Git的优势:
1. 大部分操作在本地,不需要联网。
2. 完整性保证(Hash函数)
3. 尽可能地添加,而非删除或者修改,从而能够轻松退回到历史版本。
4. 分支操作快捷流畅,并且与Linux命令全面兼容。

Git本地库与远程库的协作:


二、本地库操作
(和Linux命令是兼容的)
1. 本地库初始化 git init
* 会生成一个.git文件夹,存放本地库相关文件,不要乱动。
2. 设置签名:(设置一次需两句)
* git config user.name/user.email xxx 项目级别(仅在该本地库生效,保存在.git/config中)
* git config --global user.name/user.email xxx 系统用户级别(该OS的用户所有的本地库都适用,保存在根目录下的.gitconfig文件中)
* 至少要有一个签名
添加与上传:
5. 查看当前本地库状态 git status
* 可以查看当前在哪个branch上、现在有没有什么commit,以及现在可提交的文档。
6. 将文档加入暂存区 git add 文件名
7. 从暂存区撤出一个文档 git rm --cached 文件名
8. 提交一个文档 git commit 文件名
* 输入该命令后会进入vim编辑器,要求输入本次提交的备注。
* 也可以在commit后加上 -m "备注内容",这样就不用进vim了。
版本查看与修改:
9. 查看版本历史 git log

* space下翻页,b上翻页,q退出显示。
* 使用后可以显示出commit的哈希值、作者、日期、备注等;如果带HEAD指针,则说明是当前的版本。
* --pretty=oneline 使得每条commit只显示一条。(显示哈希值与备注)也可直接写--oneline,此时哈希值只显示一部分。该命令不显示比当前版本更新的版本。

* git reflog 显示哈希值、备注,以及版本的编号(HEAD为0,往后推)。该命令显示所有可用版本。

10. 在版本间转换(索引值法)git reset --hard 索引值(黄字哈希值)
* (^法,表示回退,每一个符号回退一步)git reset --hard HEAD^
*(~法,表示回退,后面接数字表示步数)git reset --hard HEAD~n
* 关于参数:--soft 不触碰工作区与暂存区,仅移动本地库指针;--mixed 移动本地库指针,并重置缓存区,不碰工作区;--hard 三区均受影响。
文件的比较:
11. 比较两个文件内容的区别 git diff 文件A 文件B
*文件A必须是HEAD,或者任意历史版本;文件B为工作区文件。
*如果只给出一个文件名,则将该文件与暂存区里的比较。
*如果不给出文件名,则将所有工作区文件与其暂存区比较。
分支:默认的分支为master
12. 分支的意义:并行推进多个功能开发,提高开发效率;分支之间不会相互影响

13. 查看现有分支(目前所在分支会显示绿色) git branch -v
14. 创建分支 git branch 分支名
15. 切换分支 git checkout 分支名
16. 合并分支:切换到主分支 --> git merge 从分支
* 如果两个分支都有修改,git拿不定主意的 话,就需要人工修改文件(删除特殊标记符号并修改内容)后,再add + commit。
三、Git的机制
1. git使用哈希算法中的SHA-1算法来加密数据,从而保证数据完整性。
2. 分支的实现:通过指针,每个分支都有一个指针;此外,切换分支时,也只是变换HEAD指针的指向。
四、远程库的操作
1. 查看现有远程库 git remote -v
2. 新增一个远程库 git remote add 远程库别名 远程库地址
删除一个远程库 git remote rm 远程库别名
3. 向远程库传递本地库 git push 远程库地址 远程库分支名
4. 克隆远程库到本地库 git clone 远程库地址
* 克隆后会自动init,并且创建别名(默认叫origin)。
5. 添加collaborator 去github里设置
6. pull其实是fetch+merge两步操作。fetch将远程库下载下来,作为一个新分支,通常名为oringin/master,但并不会修改工作区的文件。
* git fetch 远程库 远程分支
* git merge 远程库/远程分支
* git pull 远程库 远程分支
7. pull和clone的区别:clone是本地完全没有远程库里的分支,直接copy整个过来;pull是将远程库中的新commit与本地已有的内容合并。
8. 如果不是对远程库上最新版所做的修改,则不能直接push,远程库那边会拒绝,必须先pull下来,并且自动进入merge状态;通过修改冲突文件的内容,解决文件冲突后,add+commit+push即可,注意此时commit不带文件名。
两个远程库之间的操作:
第一步:集团B先fork一下集团A的远程库(在github上点击),此时B就有了A的远程库的副本。
第二步:在B处创建一个新文件夹,init一个本地库,clone远程库副本。
第三步:B在本地进行修改,add+commit到B的本地库,并最终push到B的远程库上。
第四步:B去A的远程库上,点击pull request;此后A就可以审核B的commit以及changed files,若A确认无误,则confirm merge,并将自己的远程库pull到本地。
六、扩展内容
SSH登陆:(一台机器仅可为一个账号设置SSH)
1. 进入根目录 cd ~
2. 清除原有 rm -rvf ./ssh
3. 生成ssh秘钥 ssh-keygen -t rsa -C 邮箱地址 (全回车确认)
4. cd .ssh 然后 cat id_rsa.pub 复制其中的值
5. 在github上的个人主页处,左边侧边栏有SSH and GPG keys,在SSH处输入你的rsa值,保存即可。
6. 返回工作目录,新建远程库的SSH链接:git remote add origin_ssh ssh地址
7. 以后往ssh这个链接push即可
Git工作流:
1. 集中式:所有修改都提交到origin/master上,SVN会使用。
2. GitFlow:


3. Forking:在GitFlow的基础上增加了pull request与审核,确保安全性以及外人的参与。