Git日常使用技巧 - 笔记
-
Git是目前世界上最先进的分布式版本控制系统
-
学习资料
- 廖雪峰
-
学习视频
- https://www.bilibili.com/video/BV1pX4y1S7Dq/?spm_id_from=333.337.search-card.all.click&vd_source=2ac127043ccd79c92d5b966fd4a54cd7
-
Git 命令在线练习工具
- https://learngitbranching.js.org/?locale=zh_CN
一、Git基础
1. 版本控制系统
1.1 集中式的版本控制系统
- 定义
- 版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器
- 缺点
- 本地没有完整的版本库历史,依赖于中央服务器,需要联网才能提交内容给中央服务器,断网状态下既不能提交,也不能回滚
- 在局域网外,如果网速过慢,提交时间过长
1.2 分布式版本管理系统
-
定义
- 分布式版本控制系统可以没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。
-
多人协作
- 每个人电脑上都有一个服务器,有着完整的版本库,你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了
- 分布式版本控制系统通常也有一台充当“中央服务器”的电脑,用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便
-
优势
- 分布式版本控制系统的安全性要高很多,每个人都是一个backup
- 每个人的本地都有完整的版本库历史,可以直接从本地服务器直接回滚,只有需要与外界同步修改时才需要联网
1.3 区别
- 集中式属于主从设计,只有中央服务器拥有完整的版本库历史,本次只有当前版本以及部分历史信息,类似于银行,自助银行终端可以向银行查询账本,如果银行没有了,则整个完整的账本也没有了
- 分布式是同步设计,每个本地都有自己完整的版本库历史,如果用于协同工作的交换服务器报废了,可以选择一份最接近的版本库提交到新的交换服务器中,以减少损失。
2. Git 安装
2.1 window git 安装
- 参考
https://www.liaoxuefeng.com/wiki/896043488029600/896067074338496
- 安装
- 从官网下载安装程序,安装成功会在在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西
2.2 linux安装
- debian和ubuntu
sudo apt-get install git
- 其他版本则官网下载安装即可
3. 工作区与版本库
3.1 工作区
- 在电脑上看到的目录,如learngit
3.2 版本库
-
工作区中有过一个隐藏的.git,不算工作区,而是版本库
-
版本库中有,暂存区(stage) 和 git自动创建的master分支, HEAD 是一个指向当前分支的指针
-
我们add 后的文件都会存在暂存区
-
git add readme.txt
-
-
git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支 -
提交后暂存区清空
二,版本库
1. 创建本地版本库
1.1 从一个空目录创建空仓库
-
创建目录
-
mkdir learngit
-
-
进入目录,执行初始化命令将目录变为Git仓库
-
git init
-
-
创建成功,则目录下多了一个.git文件,用于跟踪管理仓库,如果被隐藏则 用 ls-ah 查看所有文件
- 初始设置:设置名字和邮箱
-
名字
git config --global user.name "binge"
-
email
git config --global user.email "xxx@163.com"
-
–global 参数表示你这台机器上所有的Git仓库都会使用这个配置
-
1.2 直接从远程仓库克隆版本库到本地的空仓库
-
可以在github上找到版本库的地址,Git支持ssh协议和https协议
-
在 Git bash 打开用于保存项目的目录,执行克隆命令
-
git clone 项目的地址
-
本地找一个仓库,使用ssh协议拉取远程仓库
-
如果本地是新的git环境,可能会报错:Please make sure you have the correct access rights and the repository exists,很大可能是公钥问题
-
bash 查看是否有密码
-
cat ~/.ssh/id_rsa.pub # 控制台上输出内容
-
-
没有则新建,一路默认操作即可
-
ssh-keygen -t rsa
-
-
拷贝公钥放到github的Settings -> SSH keys 中
-
https协议拉取远程仓库
master与main分支
- main是git新的默认主分支名字
- 当本地创建版本库时,默认还是master作为主分支名字
- 当空目录clone远程库到本地,然后进入目录会发现默认的主分支名字为main
2. 删除本地仓库
-
删除仓库文件夹下隐藏的.git文件即可
-
ls -a 查看隐藏文件 rm rf .git 删除.git文件
-
3. 将文件加入版本库进行跟踪
- 在新建的仓库中的文件或者我们在克隆仓库后新建的文件,都是未被版本库跟踪的,我们可以通过命令进行跟踪
3.1 对单个/多个文件进行添加暂存区
-
在仓库文件夹下创建文件并添加暂存区,添加多个文件,则用空格隔开
-
git add readme.txt
3.2 将目录所有的文件都添加到暂存区
git add .
- 版本库只能跟踪存文本文件的改动,如txt, 对于视频等二进制文件只能跟踪大小改变,内容改变无法跟踪
- 注意事项
-
word文件是二进制格式,无法进行跟踪
-
windows自带的记事本在每个文件开头添加了0xefbbbf(十六进制)的字符,保存会乱码,避免使用,可以采用vS Code
-
3.3 添加到暂存区的文件进行提交版本库
git commit -m "提交log"
三、版本控制
1. 查看版本信息
-
查看git 历史提交日志
-
git log
-
git log --pretty=oneline
-
不会显示所有信息,只会显示版本号
-
git log --graph
-
-
图形化展示
-
-
单纯查看工作区的情况
-
git status
-
-
查看文件修改内容
-
git diff
-
-
查看工作区文件的内容
-
git cat 文件名
-
2. 管理修改
- Git的优点:
- 跟踪的是修改,而不是文件
2.1 提交文件流程
-
要提交的内容需要添加到暂存区
-
git add 文件名
-
-
将暂存区的内容提交到版本库
-
git commit -m "提交log"
-
-
本地文件修改但没有提交到暂存的内容,则不会被提交到版本库
2.2 对比差异
-
git diff 命令 不加参数,只比较比较工作区和暂存区(最后一次add)的区别
-
git diff
-
-
比较工作区和版本库(最后一次commit)的区别
-
git diff HEAD -- 文件名
-
-
比较工作区和暂存区
-
git diff 文件名
-
-
比较暂存区和版本库的区别
-
git diff --cached
-
3. 仓库版本的回退
-
git中的版本关键字
- 当前版本
- HEAD
- 上一个版本
- HEAD^
- 上上个版本
- HEAD^^
- 当前版本
-
回退到上一个版本
-
git reset --hard HEAD^
-
-
回退到指定 commit id的版本
-
git reset --hard 写差不多5位即可
-
-
回退后,想回到未来的版本,查看命令历史,可以查看对版本的操作记录,包括被操作版本的版本号
-
git reflog
-
然后根据相应的 commit id 回退的未来版本
-
3.1 reset 与 revert的区别
- 例子; 如果已经有A -> B -> C
- reset 是直接向前回滚,回滚后则后面的版本信息将消失
- 如 C提交错误的信息,想回滚到B并删除掉C的提交信息,则使用reset
- 结果:
- A -> B
- revert 是往前进,但内容回到了过去的目标版本
- 如C是正常提交信息,但由于工作原因,需要回退到B的版本内容,将来可能再改为C,则使用revert
- 结果:
- A -> B -> C -> B
4. 撤销修改
4.1 撤销最近一次工作区的修改
-
把file 文件在工作区的修改全部撤销 - 让这个文件回到最近一次
git commit
或git add
时的状态-
git checkout -- 文件名 //新版本git改版 git restore
-
情况
- 情况一:file修改后还没有add 放入暂存区,撤销后就回到跟版本库一模一样的状态
- 情况二:file已经添加到暂存区,又修改了,撤销后,就会回到添加到暂存区后的状态(最后的修改撤销了)
-
4.2 撤销暂存区的修改
-
把暂存区的修改撤销掉,重新放回工作区
-
git reset HEAD 文件名 //新版本git改版 git restore --staged
-
HEAD表示版本库的最新版本
-
4.3 场景分析
-
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时
-
git checkout
-
-
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改
- 分两步,第一步用命令
git reset HEAD <file>
,撤销暂存区的内容,放回到工作区, - 第二步按场景1操作
- 分两步,第一步用命令
5. 删除文件
- 将文件从仓库删除
git rm filename
-
如果对添加到仓库但未提交文件进行删除,会报错
-
正常删除状态
-
然后提交版本库即可
5.1 删除文件但保留在目录中(未跟踪状态)
git rm --cache filename
6. 恢复文件
-
用版本库里的版本替换工作区的版本, 丢弃暂存区该次删除操作,丢失最近一次提交后修改的内容
-
git checkout -- W文件名
-
四、远程仓库
1. 添加远程仓库,同步本地仓库
- 已经在本地创建了一个Git仓库后,想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作。
1.1 GitHub 创建空仓库
- 可以网页登录github或者通过 Desktop进行创建
1.2 将本地仓库与远程库进行关联
git remote add origin(这是git默认的名字) git@github.com:账户名/仓库名.git
# 如果添加的地址出错了,可以解除本地与远程库的关联
git remote rm origin(库名)
-
origin 是Git默认远程仓库名字,可以重命名
-
git remote rename 旧名字,新名字
-
-
如果克隆别人的仓库,在此基础上完成代码,推送到自己的仓库,可能会遇上 error: remote origin already exists.的问题
-
查看远程仓库
-
git remote -v
-
-
已经关联了仓库,把关联的这个仓库删掉
-
git remote rm origin(库名)
-
-
再重新关联自己的仓库
-
1.3 将本地库的内容,推送到远程
-
在推送前,最好先拉取更新下仓库
git pull
-
将当前分支 master 推送到远程
git push origin master
-
推送其他分支
git push origin dev
-
参数
- -u
- 第一次推送 master 分支时,加上 -u 参数,Git不但会把本地的master分支内容推送到远程新的master分支上,还会把远程的分支与本地master关联,以后的推送中或拉去中就可以简化指令
- -u
-
每次本地做了提交之后,推送到远程仓库中
- git push origin(库名) master
- 或者简单地就是 git push
-
Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入
yes
回车
五, 分支管理
- 分支有什么用?
- 当我们需要开发新功能的时候,如果可以创建一个属于自己的分支并在上面进行自己的开发工作,不会影响到别人的提交,等我们开发完毕后,再一次性合并到原来的分支上
1. 什么是分支
-
每次提交,都会生成一个提交对象,每个对象都有一个哈希值,Git都把它们串成一条时间线,这条时间线就是一个分支
-
分支就是一个包含每个提交对象的哈希值的文件,简单来说就是指向提交对象的指针
-
主分支
- master(main)
-
执行当前分支
- HEAD
-
查看当前分支
-
git log
- HEAD-> main 表示当前所在的分支
- origin/main 指定是我们远程仓库的main分支
-
查看分支列表
git branch --list
-
2. 一开始只有一条分支 master(新版本叫main)
3. 新建一个分支
- Git新建了一个指针叫
dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
# 创建新分支并切换
git checkout -b dev
# 相当于
git branch dev
git checkout dev(新版git checkput 改为 switch)
# 查看当前分支, 列出所有分支,当前分支前面会标一个*号
git branch
# 工作完,切换回到主分支
git switch master
- 从现在开始,对工作区的修改和提交就是针对
dev
分支 - 修改master分支下的binge.txt,然后提交
git commit -am 'create dev and modifile binge.txt'
- 查看所有分支的提交
- git log --all / git log --all --graph
- 切换为master分支可以看到binge.txt文件内容还是原来的内容
4. 合并分支
- 假如我们在
dev
上的工作完成了,就可以把dev
合并到master
上。最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
# 把dev分支的工作成果合并到master分支
git merge dev
- 合并后binge.txt文件内容发生改变
5. 合并后删除分支
# 合并并检查完成后,就可以删除dev分支
git branch -D dev1
# 查看结果
git branch
6. 如何恢复被删的分支
git reflog show --date=iso
- git reflog用来记录你的每一次命令,–date=iso 表示以标准时间显示,(不能用git log相关命令显示从最近到最远的提交日志,因为当分支被删掉就找不到记录)
- git show 分支id 查看提交详情
- it checkout -b 要恢复的分支名 提交记录id
六,冲突与解决冲突
1. 两个子分支都做了修改,都想合并到主分支,产生冲突
1.1 创建并切换到新分支1 dev1,修改binge.txt文件
git switch -c dev1
git add binge.txt
git commit -m "dev1 commit binge.txt"
1.2 创建并切换到新分支2 dev2,修改binge.txt文件
git switch master
git switch -c dev2
git add binge.txt
git commit -m "dev2 commit binge.txt"
-
查看提交log ,按下q键退出查看
- git log --all
-
以graph形式查看log
- git log --all --graph
-
合并dev1
-
合并分支dev2时,会因为两个分支同时修改了一个文件导致冲突
- Automatic merge failed; fix conflicts and then commit the result
1.3 解决冲突
-
查看状态
-
进入文件,手动解决冲突
-
只能保留冲突两者的其中一个部分,保存退出
-
提交
-
查看合并的log
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uiUNcHYt-1685264358904)(D:\typoraImages\image-20230525230203206.png)]
1.4 向远程库推送
- 推送master分支
- 一般推送
git push origin master
- 精简推送
git push -u origin master
- 加上 - u参数,下次只需要 git push就可以提交
- 一般推送
- 也可以推送其他的分支,如dev1, dev2
2. 主分支和子分支都做了修改,子分支想直接合并到主分支,产生冲突
- 情景
- 开发过程中,如果需要添加新功能,但不想影响主分支,新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支
解决冲突类似上一种情况
- 根据Git提示的冲突文件,手动修改冲突,改为我们希望的内容,再提交
- 最后删除新分支
- 可以通过命令查看分支树
git log -graph
七、分支管理策略
- 默认情况下,Git使用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息
1. 使用普通模式
-
Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
-
合并分支
-
git merge --no-ff -m "merge with no-ff" dev
-
–no-ff参数,表示禁用Fast forward
-
2. Fast forward模式
- 分支管理原则
- master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活
- 每个人干活都在dev分支上,开发完成后再合并到master分支
八、stash 储藏功能
-
当前正在dev上进行的工作做了一半,还没有提交,但需要新建一个临时bug分支去修复bug,修复后,合并分支,然后将临时分支删除。
-
stash
- 可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作
- stash后,切换到要进行bug修复的分支,然后建立临时分支,修复完成后并完成合并,最后删除临时分支
- git stash list 查看工作现场列表
- git stash apply 恢复现场
- git stash drop 删除现场
- 恢复现场时删除stash内容
- git stash pop
-
如果所修复bug也存在于dev分支,则可以将所修复bug的提交复制到dev分支
- git cherry-pick 提交的版本号
1、实例:功能开发到一半,突然有一个新bug需要紧急修改
-
master分支,修改binge.txt,修改了一半,然后需要切换分支修bug
-
要切换dev1分支,但因为当前master分支已经脏了,提示要么先提交,要么使用stash命令进行存储
-
git stash(git stash push) 存储后,master重新变成干净的目录
-
切换dev1分支,修改完bug后,再切换回master,就可以使用git stash apply 恢复现场
2. 可以多次 git stash
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qIVaDdbK-1685264358906)(D:\typoraImages\image-20230527002725667.png)]
-
git stash list 查看stash 记录,0表示最近一次的stash
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqOd9Cl4-1685264358906)(D:\typoraImages\image-20230527002818188.png)]
-
恢复到指定的stash 记录(只能在干净的目录进行恢复stash),但不会删除stash 记录
- git stash apply stash#{stash的id}
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HtfTc6va-1685264358906)(D:\typoraImages\image-20230527003322574.png)]
-
git stash pop
- 恢复最后一个stash, 恢复现场时删除stash内容
-
git stash drop
- 单纯删除现场