motivation
明天面试C++实习, 简历上写了熟悉git, 但其实只是简单使用过, 最多到checkout, 所以系统学习一下;
基于廖雪峰的网站 https://www.liaoxuefeng.com/wiki/896043488029600/896827951938304
杂谈
Linus两周写完的, 牛!
安装完成后的设置
1  | git config --global user.name "Your Name"  | 
基本用法
- 创建git仓库:
git init.git不可见, 可以使用ls -ah看见
 - 文件添加到仓库
git add filename.suffix
 git status可以查看仓库状态(那些文件added, 未commit, 那些修改了未added)
- add的文件提交到仓库(commit一次会提交所有add了但尚未提交的文件, 一次提交多个文件)
git commit -m "describe your modification"
 
- 查看文件怎么被修改的:
git diff- 在readme.txt后面加一句another repo后(显示删掉了一行, 添加了两行,猜测和windows记事本工作方式有关)
 
 
- 查看历史记录:
git loggit log --pretty=oneline简略输出
 
- 版本回退
- 在git中 
head表示当前版本,head^表示上一个版本, 上上个版本则为head^^, 向上100个版本为head~100 - 尝试用命令
git reset --hard head^退回上一个版本d647a add another repo - 记事本打开readme.txt, add C++这一行确实没有了, 版本确实回退
 
 - 在git中 
 
- 再返回
- 可以看到git log的输出已经只剩下前两个版本 了, 这时候我们想回到
add C++的版本, 就该使用版本号(最短可分辨前缀即可)git reset --hard 1abd - 可见确实我们又在
add C++的版本, 而且记事本打开验证, add C++又回来了 
 - 可以看到git log的输出已经只剩下前两个版本 了, 这时候我们想回到
 
- 找回所有操作记录
git reflog(忘了add C++的commit id, 然后又关机了, 找不回了, 就可以用这个) 
- 撤销修改(修改未add到stage)
git checkout -- xxx.txt- 让这个文件回到最近一次
git commit或git add时的状态。 git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令
 
- 撤销修改(修改已经add到stage)
- 组合拳
 git restore --staged xxx, 这条命令执行后xxx已经是unstaged的状态了, 此时stage无修改, 工作区有修改git checkout --xxx, 清空工作区修改
 
- 文件删除
- 文件管理器删除
xxx git rm xxxgit commit -m "delete xxx"
 - 文件管理器删除
 - 删错了想要弄回来
git checkout --xxxgit checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
 
git原理
git add xxx之后,xxx会被添加到暂存区stagegit commit -m "finish xxx"之后,xxx会被添加到当前分支(目前是master)
远程
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name>推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
 - 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>推送就能成功! 
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结
- 查看远程库信息,使用
git remote -v; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
 - 从本地推送分支,使用
git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name; - 从远程抓取分支,使用
git pull,如果有冲突,要先处理冲突。 
分支管理
- 创建分支 并 切换
 
1  | git checkout -b dev  | 
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
1  | git branch dev  | 
- 用
git branch命令查看当前分支: 
1  | git branch  | 
git branch命令会列出所有分支,当前分支前面会标一个*号。然后,我们就可以在dev分支上正常提交.
- 现在,
dev分支的工作完成,我们就可以切换回master分支 
1  | git checkout master  | 
切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
- 我们把
dev分支的工作成果合并到master分支上 
1  | git merge dev  | 
git merge命令用于合并指定分支到当前分支。
注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
合并完成后,就可以放心地删除dev分支了:
1  | git branch -d dev  | 
切换分支这个动作,用
switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:- 创建并切换到新的
dev分支,可以使用:git switch -c dev - 直接切换到已有的
master分支,可以使用:git switch master 
- 创建并切换到新的
 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用
git log --graph命令可以看到分支合并图。合并分支时,加上
--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
命令
git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id;命令
git tag -a <tagname> -m "blablabla..."可以指定标签信息;命令
git tag可以查看所有标签。命令
git push origin <tagname>可以推送一个本地标签;命令
git push origin --tags可以推送全部未推送过的本地标签;命令
git tag -d <tagname>可以删除一个本地标签;命令
git push origin :refs/tags/<tagname>可以删除一个远程标签。