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 log
git 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 xxx
git commit -m "delete xxx"
- 文件管理器删除
- 删错了想要弄回来
git checkout --xxx
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
git原理
git add xxx
之后,xxx
会被添加到暂存区stage
git 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>
可以删除一个远程标签。