## git 简介
git是一个分布式的版本控制系统,一个git工程有三个工作区域:
* 工作目录
* 暂存区域
* 本地仓库
git add之后是到了暂存区域,git commit之后是到了本地仓库。
## git-config全局配置
```bash
$ git config --global user.name "<user_name>"
$ git config --global user.email "<user_email>"
```
## git常用命令
* git add xxx 添加文件到暂存区
* git rm xxx 删除文件,替代物理删除文件,然后提交
* git commit -m "xxx" 提交更改到本地仓库
* git push 推送更改到远程分支
* git pull 从远程分支拉取更改
* git reset HEAD xxx 如果某个文件被add了,但不想commit可以恢复
* git branch xxx 创建某个分支
* git checkout xxx 切换到某个分支
* git checkout -b xxx 新建某个分支并切换过去
* git branch -av 查看所有本地分支+远程分支及对应版本号
* git merge --no-ff xxx 合并分支
* git branch -d/-D xxx 删除本地分支(区别是是否被merged)
* git diff xxx 查看文件改动
* git log xxx 查看文件变动日志
##### git fetch 和 git pull
git fetch就是将远程的分支拉取到本地远程,具体有几种写法:
* git fetch origin
将所有的origin远程分支都拉取到本地远程,并且名字一一对应
* git fetch origin xxx
把xxx分支拉取到本地远程,并且FETCH_HEAD指向它
* git fetch origin xxx:yyy
把xxx分支拉取到本地远程和本地,并且将本地分支命名为yyy(这样在本地就存在本地分支和本地远程分支)
git branch查看本地分支,-r选项查看本地远程分支,-a选项查看所有分支
```bash
$ git brand -r
origin/HEAD -> origin/master
origin/develop
origin/master
$ git brand -a
develop
* master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/master
```
* git pull == git fetch + git merge
git pull相当于从远程分支fetch到本地远程分支后,再merge到本地分支。
## git统计人员代码贡献量:
```bash
git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done
```
## git撤销操作
##### 撤销本地工作目录的更改
如果更改了本地文件还没有git add,那么可以使用如下命令撤销修改:
```bash
$ git checkout -- <file>
```
git checkout会把工作目录里的文件修改到git之前记录的某个状态,默认情况下恢复到当前分支的最后一次commit。
##### 撤销暂存区的修改(即撤销git add)
如果已经通过git add将修改添加到暂存区,但还没有commit,那么可以使用如下命令撤销到git add之前的状态:
```bash
$ git reset HEAD <file>
```
##### 撤销本地仓库的更改(即撤销git commit)
如果在本地commit了一些内容但还没有push,这时你想撤销提交可以使用如下命令:
```bash
$ git reset <commit_id>
// 或者 git reset --hard <commit_id>
```
git reset会把代码返回到指定的commit状态,这样就像是这些提交从来没有发生过。默认情况下git reset会保留工作目录,这样提交是没有了,但是修改的内容还在磁盘上,这是一种安全的选择。如果希望一步就撤销提交和修改的内容,就加上 --hard 选项。
##### 撤销已push的更改(即撤销git push)
如果已经执行了git push把内容发送到了远程仓库,如果现在想撤销某一个commit,可以用如下命令:
```bash
$ git revert <commit_id>
```
git revert会产生一个新的commit,它和指定的commit是相反的(或者说是反转的),任何从原先的commit里删除的内容会在新的commit里被加回去,任何在原先的commit里加入的内容会在新的commit里被删除。这是git最安全、最基本的撤销场景,因为它并不会改变历史,所以你现在可以git push新的“反转”commit来抵消你错误提交的commit。
## git flow分支模型
![image](http://note.youdao.com/yws/public/resource/5dbc3fd98ac889fc3b7ad9b8cb390295/xmlnote/WEBRESOURCE35b6b51c77a78d4a99af84ada2b856c5/4777)
主要分支:
* master分支
>这个分支是最近发布到生产环境的代码,这个分支只能从其他分支合并,不能在这个分支直接修改。
* develop分支
>这个分支是我们的主开发分支,包含所有要发布到下一个release的代码,这个主要合并其他分支,比如feature分支。
辅助分支:
* feature分支(分支名:feature/*)
>这个分支主要是用来开发一个新的功能,一旦开发完成,我们合并回develop分支并进入下一个release。
* release分支(分支名:release-*)
>当你需要发布一个新release的时候,我们基于develop分支创建一个release分支,测试完成后,我们将release分支合并到master和develop分支。
* hotfix分支(分支名:hotfix-*)
>当我们在production发现新的bug时,我们需要创建一个hotfix,完成hotfix后,我们合并回master和develop分支。
### git flow代码示例
##### 创建develop分支(也可以使用gitlab在远程创建,然后将develop分支clone到本地)
```bash
$ git branch develop master
$ git push -u origin develop
```
##### 开始新的feature分支
```bash
$ git checkout -b feature/some-feature develop
$ git push -u origin feature/some-feature
# 做一些改动
$ git status
$ git add
$ git commit
$ git push
```
##### 完成feature
```bash
$ git checkout develop
$ git pull
$ git merge --no-ff feature/some-feature
$ git push
# 删除本地分支
$ git branch -d feature/some-feature
# 删除远程分支
$ git push origin --delete feature/some-feature
```
##### 开始release
```bash
$ git checkout -b release-1.0 develop
$ git push -u origin release-1.0
# 如果有改动
$ git status
$ git add
$ git commit
$ git push
```
##### 完成release
```bash
# 合并到master
$ git checkout master
$ git pull
$ git merge --no-ff release-1.0
$ git push
# 合并到develop
$ git checkout develop
$ git pull
$ git merge --no-ff release-1.0
$ git push
# 删除本地分支
$ git branch -d release-1.0
# 删除远程分支
$ git push origin --delete release-1.0
# 打标签
$ git tag -a v1.0 master -m "version 1.0"
# 推送本地tag到远程
$ git push origin v1.0
# 如果要推送本地所有的tag使用--tags参数
$ git push origin --tags
```
##### 开始hotfix
```bash
$ git checkout master
$ git pull
$ git checkout -b hotfix-1.1 master
# fix bug
$ git status
$ git add
$ git commit
```
##### 完成hotfix
```bash
# 合并到master
$ git checkout master
$ git pull
$ git merge --no-ff hotfix-1.1
$ git push
# 合并到develop
$ git checkout develop
$ git pull
$ git merge --no-ff hotfix-1.1
$ git push
$ git branch -d hotfix-1.1
$ git tag -a v1.1 master -m "version 1.1"
$ git push origin --tags
```
### git 忽略文件提交 .gitignore 文件说明
* 从未提交过的文件可以用.gitignore
> 也就是添加之后从来没有提交(commit)过的文件,可以使用.gitignore忽略该文件
* 已经推送(push)过的文件,想从git远程库中删除,并在以后的提交中忽略,但是却还想在本地保留这个文件
> 执行命令:git rm --cached Xml/config.xml
* 已经推送(push)过的文件,想在以后的提交时忽略此文件,即使本地已经修改过,而且不删除git远程库中相应文件
> 执行命令 git update-index --assume-unchanged Xml/config.xml
* 后面的 Xml/config.xml 是要忽略的文件的路径。如果要忽略一个目录,打开 git bash,cd到 目标目录下,执行:
> git update-index --assume-unchanged $(git ls-files | tr '\n' ' ')
* gitignore 配置
> https://github.com/github/gitignore
比如有一个配置文件 jdbc.properties 记录数据库的链接信息,每个人的链接信息肯定不一样,但是又要提供一个标准的模板,用来告知如何填写链接信息,那么就需要在git远程库上有一个标准配置文件,然后每个人根据自己的具体情况,修改一份链接信息自用,而且不会将该配置文件提交到库!