> Git
---
###### 之前的笔记
```
step:
git status
git add xxx
git commit -m
git push
获取分支 git branch
获取全部分支包括远程端的 git branch -- all
切换到某一个分支 git checkout xxx (表示在众分支中检出)
合并分支 将zzz分支合并到当前分支(当前分支是master)
git merge zzz
初始化仓库 git init
查看用户名和邮箱地址
git config user.name
git config user.email
修改用户名和邮箱地址:
$ git config --global user.name "username"
$ git config --global user.email "email"
```
- others.一点儿git命令
```
删除本地分支:git branch -d 分支名(remotes/origin/分支名)
强制删本地:git branch -D 分支名
删除远程分支:git push origin --delete 分支名(remotes/origin/分支名)
```
---
---
git内部commit, tree, blob 三者的关系如下
![image](https://images2018.cnblogs.com/blog/682975/201805/682975-20180529135816368-253183375.png)
```
Git => 文件 -> tree -> blob -> 内容
```
---
- Git的全局配置
```
$ git config --global user.name "username"
$ git config --global user.email "email"
```
其中,缺省等同于<code>local</code>,eg:
```
git config --local (local只对某个仓库有效,必须在某个仓库下面才能用)
git config --global (global对当前用户所有仓库有效)
git config --system (system对系统所有登录的用户有效)
显示config的信息,则加 --list,eg:
git config --list --local
```
- 新关联仓库
```
1. 关联远程仓库
git remote add origin url.git
2. 关联远程分支
git branch --set-upstream-to=origin/master
3. 释权
git pull origin master --allow-unrelated-histories
```
- 对一个文件重命名,需要执行三步(旧方法):
```
1. mv readme readme.md
2. git add readme.md
3. git rm readme
分别是替换(原理是新建了一个文件,并且把原来的删除)。把新建的那个文件添加到暂存区,把原本已经有的那个老文件删除
```
- 对一个文件重命名,需要执行三步(新方法):
```
git mv readme readme.md
// 这个命令直接代替了上面的3个步骤的命令
此时再直接 commit , 都不需要的再 add 的
```
- 还原当前的操作,清楚暂存区<code>**git reset --hard**</code>,这个操作比较危险
```
git reset --hard
这个命令会清空当前的暂存区,让当前的环境中没有可以提交的。即没有删除也没有add进去。但是该命令不会清楚之前的历史记录即 git log
```
- 查看提交日志
```
1. 查看笼统日志: git log
2. 查看简约日志,只包含提交的Message,不显示时间和用户 git log --oneline
3. 只查看最近的几次日志提交 : git log -5
4. 查看所有分支的所有提交日志 : git log --all
5. 带点图形化的线条查看日志分支的从属关系: git log --graph
6. 整合一下: git log --all --oneline -n4 --graph [查看所有分支的、简约简单、合并起来的总的前4条 图形化展示。不是每个分支的前4条,是所有分支的提交记录按照时间合并在一起总的前4条]
如果 --all后面跟一个其他的分支名称的话是不起作用的,eg:[ --all master];要查看具体的哪个分支要用分支名而不是all了,eg: git log master ....
```
- 查看分支
```
git branch 查看本地分支
git branch -v 查看本地有哪些分支,和每个分支最后一次的提交Message
git branch -a 查看所有的分支
git branch -r 查看远程的分支
```
- 切换/新建分支
```
=> git checkout -b [branchName] [logId]
新创建一个 基于提交记录在[logId]的代码之上,名称为[branchName]的分支
```
- 查看 类型或者内容
```
git cat-file -t [commit ID] 查看文件的类型
git cat-file -p [commit ID] 查看文件的内容
```
- 修改已经提交的git message
```
git commit --amend 即可进入vim进行编辑最后一次的提交的Message
提交后的属性信息是,别人创建了这一次的提交,我修改了这一次的提交
```
- git rebase 变基[ 修改 之前的某次提交的git message内容]
```
本次是修改 之前某次提交的message的内容
重点: 如果要修改倒数第2条commit ID的Msg,那么就需要倒数第3条的commit ID来操作
eg: shell:=> git log
commit abc123344345364456 "最后一次提交"
cimmit def2342343453453456 "倒数第二次提交"
cimmit ghi2342343453453456 "倒数第三次提交"
我现在要修改倒数第二次的提交message,那么命令就是:
git rebase -i ghi2342343453453456
进入后,pack表示保持不动,reword表示替换更改
进入后会看到两行pack,第一行的pack是当前要修改的message,所以将pack改成r(reword),此时不修改message。第二行的是父message,所以不动它,就是pack,也不改动message。保存退出
此时会弹出一个新的弹窗,在这个新的弹窗里面再修改第一行自己想要的message,再保存退出.此时就已完成了
处理完了后,会出现分离头指针的现象
```
- 把连续的多个commit整理成1个
```
现在有 a、b、c、d 四次提交记录。a是时间最新的提交,d是时间最老的提交。
现在将abcd四次提交记录合并成一次提交记录。即:
git rebase -i d 进入交互式环境
在这个交互式环境中找到这abcd四次提交,四次之外的提交都不动。四次提交基于时间最新的a来提交,那么a前面依然是pick,不过,b/c/d前面就是s(squash[合并到前面]),保存退出
此时会弹出一个新的界面。在这个新的界面中已经出现了前面四次提价的message,此时在这个界面的第一行输入,"这一次合并的message或者这次合并的原因"
保存退出
```
- 把间隔的几个commit整理成1个
```
现在 a,b,c,d四次提交记录,要将第a次和第d次提交记录合并
git rebase -i d 进入交互式界面
里面可能会存在 a,b,c的信息,但是没有d的信息,所以,就要在交互式界面的最顶端写上 "pick d.id d.message",同时,将最下面那条信息(即a的提交记录)删除,保存退出
此时会弹出一个新的弹窗,输入这一次合并的message
如果在这两个步骤中脱落了或者异常退出或关闭,此命令git rebase --continue可以用来继续执行
```
- 比较 ++*暂存区*++ 和HEAD所含文件的差异
```
git diff --cached
// 如果没有弹出任何的话,表示工作区与暂存区与HEAD里面是完全一致的
```
- 比较工作区 与 暂存区的区别
- 将暂存区的文件恢复到原来的工作区(或 HAED ,因为最干净的时候是工作区与HEAD是一致的 )
```
git reset HEAD
git diff --cached
// 第一步是恢复(全部在暂存区的),第二步是看看有没得啥区别。没区别表示完全的从暂存区恢复到工作区
git reset HEAD -- index.html readme.md
恢复在暂存区中的其中的某个文件,使其与HEAD代码一致
```
- 将工作区的更改恢复到暂存区
```
git checkout -- src/main/java/utils/IpUtils.java (被修改的那个文件)
```
- 消除最近的几次提交
```
git reset --hard HEAD.ID
// 即回到HEAD.ID这一个版本。这个版本之后的版本就完全的抛弃了
```
- 回退致任意版本
```
git reset --hard e377f60e28c8b84158
```
- 查看两个不同的分支中,同一个文件的差别
```
git diff dev master src/main/java/utils/IpUtils.java
// 查看dev环境和master环境中的 src/main/java/utils/IpUtils.java这个文件的差别
或者dev.commit.id 与 master.commit.id 即:
git diff dev.commit.id master.commit.id
```
- 删除一个文件
```
git rm fileName.
// 这样删除后,操作记录直接保存在暂存区
```
- .gitignore不生效
```
#此为注释 – 内容被 Git 忽略
.sample # 忽略所有 .sample 结尾的文件
!lib.sample # 但 lib.sample 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
.gitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的
那么解决方法就是先把本地缓存删除(改变成未被追踪状态),然后再提交:
git rm -r --cached .
git add .
git commit -m 'update .gitignore'
```
- 著名的压栈 !!!
```
git stash (对当前修改的代码进行压栈)
git stash list (查看栈中是否有被压栈的记录)
放置当前正在修改的代码,(将这些代码压到栈中保存)
此时工作区的代码,是HEAD的干净代码, git diff / --cached 都没有差别的。
此时就可以完整干净的去开发
当开发完成后需要将之前临时修改的代码给弹出来:
git stash apply (恢复临时代码到工作区,并且记录依然在压栈中;可以反复弹栈)
git stash pop (恢复临时代码到工作区。但是会删除这条记录,仅能用一次)
如果有出错,表示没有恢复干净,执行:
git rest --hard HEAD
```
评论区