Git
主要参考廖雪峰的教程
什么是Git
Git是目前世界上最先进的分布式版本控制系统(没有之一)
- 版本管理系统
 - 不必联网
 - 强大的分支管理
 - 效率高,简单,流行
 
Git安装
Linux & Windows安装
mac上安装
Git官网下载安装 或 从AppStore安装Xcode,Xcode集成了Git,不过默认没有安装,你需要运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了.
安装登录
打开Terminal,命令行输入
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
git config参数--global表示该机器全局使用这个配置
创建版本库(repository)
创建
$ mkdir learngit
$ cd learngit
$ pwd
- 指令一创建目录
 - 指令二加载目录
 - 指令三显示当前目录 即为创建一个文件夹并加载
 
Attention:不要有中文
初始化
将git仓库初始化(创建.git文件夹)
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
返回告诉你这是个空仓库(empty Git repository)
Attention:如果没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah命令就可以看见.
添加文件
文件需在库目录下
git add添加文件
$ git add <file>
git add一次可提交多个文件及文件夹
$  git add <file> <Folder>
git commit让文件提交到仓库
$ git commit -m "Anything you want"
git commit后的-m是提交声明
时光穿梭机
status & diff
$ git status
# On branch master
# 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:   <file>
#
no changes added to commit (use "git add" and/or "git commit -a")
git status命令可以让我们时刻掌握仓库当前的状态,上面的命令告诉我们,被修改过了,但还没有准备提交的修改.
git diff可以查看文稿具体是那里被修改了
版本回退
git log命令显示从最近到最远的提交日志(可以加上--pretty=oneline参数精简显示)
在Git中使用HEAD表示当前版本,用^表示向上一个版本
例:HEAD^就是上一版本,HEAD^^是上上版本
同时也使用十六进制码表示版本编号(commit ID),也可以使用这个回退版本
使用git reset回到相应的版本
$ git reset --hard HEAD^
Attention:返回旧版本后,新版本的版本ID号将无法通过log查找
git reflog记录了每一次指令,因此可以凭借这个前进版本
工作区和暂存区
工作区(Working Directory)
即为当前编辑目录
版本库(Repository)
.git目录中,其中包含暂存区(stage),有第一个分支master,以及指针HEAD.
git实际运作模式
- 
    
git add实际上是将文件存入暂存区(stage) - 
    
git commit提交更改,将暂存区(stage)区内容提交的当前分支 
管理修改
用git diff HEAD -- <file>可以查看工作区与版本库中最新版本的区别
撤销修改
git checkout -- <file>可以丢弃工作区的修改
Attention:--参数非常重要,若丢失指令变为切换到另一分支
删除文件
git rm <file>可以从版本库中删除file,同时要git commit提交修改
远程仓库
- 
    
打开
Terminal$ ssh-keygen -t rsa -C "youremail@example.com"创建SSH Key.
- 可以在用户主目录里找到
.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对.id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人 
 - 可以在用户主目录里找到
 - 
    
登录GitHub,在Account setting中设置SSH Keys,粘贴
id_rsa.pub文件内容 
添加远程库
- 
    
在GitHub上创建新的版本库(Repository)
 - 
    
在本地运行
$ git remote add projectname git@github.com:Username/Repositoryname.git关联远程仓库
 - 
    
git push推送本地内容到远程库$ git push -u projectname master- 第一次推送
master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令(去掉-u). 
 - 第一次推送
 
从远程库克隆
$ git clone git@github.com:Username/Repositoryname.git
git的远程操作主要由
- 
    
git clone
 - 
    
git remote
 - 
    
git fetch
 - 
    
git pull
 - 
    
git push
逻辑关系简图:

 
分支管理
创建与合并分支
- 
    
创建分支
$ git checkout -b dev创建一个名为dev的分支,
-b表示创建并切换,相当于:$ git branch dev $ git checkout devgit branch可以查看当前分支 - 
    
合并分支
先切换到主要分支
$ git checkout master再合并dev到当前分支(master)
$ git merge dev - 
    
删除分支
使用
-d参数$ git branch -d dev - 
    
小结
Git鼓励大量使用分支:
查看分支:
git branch创建分支:
git branch <name>切换分支:
git checkout <name>创建+切换分支:
git checkout -b <name>合并某分支到当前分支:
git merge <name>删除分支:
git branch -d <name>如果分支尚未合并就要删除,那么需要强行删除
强行删除分支:
gitbranch -D <name> 
解决冲突
当不同分支编辑同一个文件的时候,在分之合并的时候就会出错,这种时候需要人工解决冲突
技巧:使用git log --graph查看当前分支情况,使用廖雪峰的教程示例代码
$ git log --graph --pretty=oneline --abbrev-commit
*   59bc1cb conflict fixed
|\
| * 75a857c AND simple
* | 400b400 & simple
|/
* fec145a branch test
...
分支管理策略
使用参数--no-ff表示禁用Fastforward
$ git merge --no-ff -m "merge with no-ff" dev
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了.
所以,团队合作的分支看起来就像这样:

Bug分支
git stash可以将当前分支的未提交内容暂存
可用git stash list查看之前stash的内容
两种恢复方式:
- (不推荐)用
git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除 - (推荐)使用
git stash pop,恢复同时删除stash 
多人协作
参考之前Git远程操作简图
多人协作的工作模式通常是这样:
- 首先,可以试图用
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
ps.查看远程库信息git remote -v
标签操作
git tag查看标签
git tag <name>创建<name>标签
默认标签是打在最新提交的commit上,可以使用git tag <tagname> <commitid>将标签打在指定commit上
Git设置
colorUI
$ git config --global color.ui true
#设置彩色UI,推荐开启,关键信息更加醒目
.gitignore
让Git忽略掉一些文件或者文件夹
GitHub已经帮你整理了常见的语言的.gitignore文件,只需要你下载下来放入目录
.gitignore也要加入.git
自定义.gitignore:
忽略一种文件: *.txt 忽略掉目录下以.txt结尾的文件
忽略文件夹: Floder或/Floder忽略掉Floder文件夹
忽略某目录下文件: Floder/忽略Floder目录下文件
文件中可以使用#进行注释
stm32注意
# stm32标准库.gitignore文件内容
/OBJ
*.bat
配置别名
$ git config --global alias.st status
这样就可以使用st代替status,--global参数是全局参数,这些指令在这台电脑下通用
实际上就是往配置文件中添加设置
加上--global就是在用户主目录的.gitconfig中配置
没有--global就是在.git/config文件中
# 个人使用
[alias]
	co = checkout
    ci = commit
    br = branch
    st = status
	lg = log --graph --pretty=oneline --abbrev-commit