入职前学了一些git的基础,后来在开发过程中遇到了git回退、“后悔”之类的问题,便索性完整的过了一遍。
练习地址
https://learngitbranching.js.org/?locale=zh_CN
Git 分布式版本控制器
相较于cvs
、svn
这类集中式版本控制器,git的优势在于:
本地版本控制、重写提交说明、可以退回“后悔”、分支系统等。
SVN:增量的分支系统
Git:全量的分支系统(每一个版本都包含全部的文件,时刻保持数据的完整性)
git安装
- 网址:
msysgit.github.io
- 安装:
Use git from git bash only..
,其他默认下一步 - 配置path:
F\SystemApp\Git\bin
- 配置git(用户名+邮箱):右键选中
Git Bash Here
git config --global user.name "CTX"
git config --global user.email "348958520@qq.com"
(注:--system
为整个计算机、--global
为当前用户、--local
为当前项目)
建立git连接
- 建立ssh免秘钥登陆
本地生成:ssh-keygen -t rsa -C 348958520@qq.com
+ 一直回车
(默认存放地址:C:UsersCTX.ssh)
发往远端:(个人GitHub→Settings→SSH and...→New SSH:title[协作用户名]+Key[C:\Users\CTX\.ssh\id_rsa.pub的内容]
测试连通:ssh -T git@github.com
(若C:\Users\CTX\.ssh
中出现known_hosts
文件则表示成功连通)
- 把本地文件初始化为git项目:
文件夹里右键选中 Git Bash Here
+ git init
- 在GitHub上新建一个仓库生成(区分大小写):
git@github.com:TangSong99/Git_Test.git
- 本地项目和远程仓库关联
git remote add origin git@github.com:TangSong99/Git_Test.git
用git remote -v
查看是否关联,若本机之前已存在可以先执行git remote rm origin
第一次发布
git add .
将当前文件写入暂存区git commit -m "注释内容"
(-m "注释内容"可以替换为回车进行多注释声明)
暂存区提交到本地分支,默认master(重复提交会显示On branch master nothing to commit, working tree clean
,因为commit将文件从暂存区提交到对象区了,暂存区没有东西)git push -u origin master
作为主分支提交到仓库中,若不是新仓库即使是清空仓库也会失败(因为先前仓库的库版本会有一个commit readme.md
而本地没有导致两个版本不一致,可以用pull更新本地再上传或者git push -f origin master
强制覆盖。如果为空仓库建议重新建立仓库。)
第一次下载
git clone git@github.com:TangSong99/Git_Test.git
下载到本地,再次强调仓库地址区分带小写!
提交本地更新(本地→远程)
git add .
git commit -m "提交到分支"
git push origin master
拉取仓库更新(远程→本地)
git pull
团队协作
发起者:
GitHub仓库的Settings→Manage acess→invite a collaborator→合作者GitHub全名/邮箱→发送邀请链接
协作者:
点击链接参与合作:clone、编写、提交更新(add/commit/push)
实际开发中的项目拉取
实际开发中公司一般用的是自己的GitLab,用申请到的帐号进行登陆,进去后先配一下本地的公钥,git中的name和email也要改成要求的格式。然后进去到对应的项目直接拉取master,开发时再在本地切换需要的分支就行了。
//本地git账户改名(修改之前的提交仍然使用的是之前的邮箱和名字),项目提交前也可以再检查一遍
git config --global "caitianxin"
git config --global "caitianxin@taqu.cn"
//下载项目,SSH下载不了就尝试用HTTP,HTTP需要帐号密码验证
git clone [global's SSH/HTTP]
//打开项目切换分支,VSCode左下角直接切换分支进行开发,可以查看当前分支:
git branch
//要提交前一定要记得先拉取项目到最新!
git pull
//(将AppVersion目录下的文件)提交到暂存区
git add src/views/appConfig/appVersion
//多个文件写法(逗号+空格)
git add src/views/a.vue, src/views/b.vue
//中途可以查看一下是否成功
git status
//提交到本地分支
git commit -m "注释尽量要详细、具体"
//提交到远程仓库
git push
Git执行流程
Git 3+1种状态:
(已管理):项目中被git管理的部分才有以下三种状态
已修改(modified):修改后的代码、暂存区回到工作区(git rm --cached
)
已暂存(staged):执行add后
已提交(commited):执行commit后
(注:新版git用restore替换checkout)
通过git init
将目录纳入git管理,默认为master分支。执行后会生成.git
文件,它是git版本控制的目录。
Git回退、删除、后悔、忽略、版本穿梭
- 从暂存区回到工作区:
git reset head [filename]
删除已提交到对象区的文件1
git rm a.txt
//删除本地文件和对象区中的a.txt,再把删除文件的操作指令退回到暂存区git commit -m "彻底删除a.txt"
//相当于重新提交了上一条语句,将a.txt彻底删除git rm xx
后的后悔操作git restore --staged a.txt
git restore a.txt
- 删除已提交到对象区的文件2
rm a.txt
//删除本地文件和对象区中的a.txt,再把删除文件的操作指令退回到工作区git add .
//提交删除指令到暂存区git commit -m "彻底删除a.txt"
- 重命名(实质上是拷贝一份新名称文件,再把旧的删除)
git mv a.txt aa.txt
,也可以直接mv a.txt aa.txt
- 注释重写
git commit --amend -m '修正'
忽略(配置)文件,空文件夹默认忽略
.gitignore
*.properties !a.properties #忽略整个目录底下文件 dir/ #忽略任意级目录下的txt dir/**/*.txt
- 回退到上一次版本(多人合作的时候要回退最好用指定sha1值或用
revert
替代reset
)git reset HEAD^
回退到上两次用HEAD^^
,上n次用HEAD~n
- 指定sha1回退
git reflog
查看记录,记录所有操作。可以帮助我们 实现“后悔”操作。需要借助于良好的注释习惯git reset --hard [sha1值的前几位]
reset是将之前增加到暂存区的内容回退到工作区
【注:git reset三种方式的区分放在下面的踩坑场景中了】
Git 日志
git log
/ git log -number
:查看(最近次数)提交的日志
$ git log
commit d433136c1d275fa26fdbf835cc4b2ecd4aeae4ec (HEAD -> master)
Author: CTX <348958520@qq.com>
Date: Sun Oct 11 11:00:03 2020 +0800
更新时间2020年10月11日 11:00:22
commit 8bca948ba633f2d93231560573c97da88df74a5b (origin/master, origin/HEAD)
Author: CTX <348958520@qq.com>
Date: Sun Oct 11 09:49:54 2020 +0800
更新git进阶
commit 480e0a9184d0f1691de70afe4bcad5943b41b2b8
Author: 唐宋丶 <52407046+TangSong99@users.noreply.github.com>
Date: Sun Oct 11 09:08:36 2020 +0800
Create 仓库说明.txt
git log --pretty=online
:单行显示简要信息
$ git log --pretty=oneline
d433136c1d275fa26fdbf835cc4b2ecd4aeae4ec (HEAD -> master) 更新时间2020年10月11日 11:00:22
8bca948ba633f2d93231560573c97da88df74a5b (origin/master, origin/HEAD) 更新git进阶
480e0a9184d0f1691de70afe4bcad5943b41b2b8 Create 仓库说明.txt
git log --pretty=format:"%h - %an ,%ar : %s"
:自定义格式化输出
$ git log --pretty=format:"%h - %an ,%ar : %s"
d433136 - CTX ,7 minutes ago : 更新时间2020年10月11日 11:00:22
8bca948 - CTX ,77 minutes ago : 更新git进阶
480e0a9 - 唐宋丶 ,2 hours ago : Create 仓库说明.txt
其中commit后面跟着的是用sha1计算出的随机数,用于区分是哪一次提交
git log&relog
git log
命令可以显示所有提交过的版本信息git reflog
可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)
例如:执行git reset --hard HEAD~1
,退回到上一个版本,用git log则是看不出来被删除的commitid,用git reflog则可以看到被删除的commitid,我们就可以买后悔药,恢复到被删除的那个版本。
Git分支
分支含义为一个commit链,一条工作记录线
git branch
查看分支git branch [branch's name]
创建分支git checkout [branch's name]
切换分支git checkout -b [branch's name]
创建并切换分支(存在就直接切换)git branch -d [branch's name]
删除分支(不能删除自身和“未合并”内容,未合并可以-D强行删除)git branch -m [old name] [new name]
分支重命名git branch -f [branch's name] [HashCode]
强行将分支指定到指定的HashCodegit merge [branch's name]
(主分支执行的)合并操作(合并增/删操作)
如果一个分支靠前(dev),另一个落后(master)。如果不冲突的话, master可以通过 merge 直接追赶上dev,称为 fast forward。git rebase [branch's name]
(子分支执行的)合并操作git rebase [branch1] [branch2]
将b2合并到b1git checkout [HashCode]^^/[HashCode]~2
移动HEAD指向指定HashCode的父父节点git cherry-pick [HashCode1] [HashCode2] [HashCode3]
根据HashCode将指定分支s复制到当前分支下git rebase -i [HashCode1]
通过可视化界面对HashCode1以后的分支进行删除或者排序git fetch
跟git pull很类似,但是pull是只拉取当前分支到最新,而fetch是拉取所有分支到最新,并且不会切换当前分支
Git现场
stash为保存现场的意思,在功能未没有开发完毕前,不建议commit,且不能切换分支。若要切换要保存现场。
- 保存现场
git stash
- 还原现场(新的不动,旧的替换)
git stash pop
还原并删除保存git stash apply
还原但不删除保存 - 查看现场
git stash list
其他
剩下一些差异性、GitHub上的操作、SubTree、Gretty以及GitLab的配置使用
前面的比较简单,后面的目前还用不到,留个坑后续遇到在学吧
Git进阶
记一次Git旧版本覆盖本地代码后的找回
场景:
修改完代码后忘记先pull拉取到最新版本了,直接commit后无法提交报错
error: Your local changes to the following files would be overwritten by merge:
.env.development
vue.config.js
Please commit your changes or stash them before you merge.
解决方案:
卡在暂存区,这时候应该只需要用下面方法撤销commit即可,
git stash
git pull
git stash pop
但是我看了第一篇公众号的方法直接执行了git rebase -i HEAD^
导致本地代码直接被昨天提交的覆盖了,真刺激。VSCode没有自带Local History插件后面用一下方法解决:
git reflog //查看最近提交状态及其更新的时间
24d45df5 HEAD@{6}: commit: Android/IOS版本更新
git reset --hard 24d45df5 //回退版本号
【提交前一定要pull同步更新代码!!!】
我的一个朋友踩的坑
场景1:
-commit完后,打算-push时,发现不小心添加了还不想要提交的文件(没开发完只是-add了)。
解决方案:
要注意的是,我之前是因为本地-commit后一番操作变成前一天的版本覆盖了本地,所以本地也要变成-commit那一次的状态,需要用reset --hard
。
而这次只是提交了还不想提交的东西,所以用reset --soft
回退到暂存区的就够了。
1、git log 查看当前分支的历史记录
2、找到你想恢复到的ID,然后 git reset --soft ID
3、这样就恢复到了提交之前的状态。被修改提交的文件会被存放在暂存区中,再次提交只需要-commit
git reset 三种回退方式
git reset --soft HEAD~1 head树回到上个版本
回退一个版本,清空对象区,暂存区、工作区都不变,所以本地代码也不变。再次提交只需要-commit
git reset (--mixed) HEAD~1 head树、index树回到上个版本
回退一个版本,清空对象区和暂存区,工作区不变所以本地代码不变。再次提交需要-add、-commit。
git reset --hard HEAD~1 三棵树都回到上个版本
回退一个版本,清空对象区、暂存区和工作区,所以本地代码会被覆盖。
场景2:
当前分支工作一半(部分已经-add),需要切换的新的分支进行工作
解决方案:
1、git stash 暂存区的文件贮藏起来
2、切换分支
3、处理完新分支后回到之前的分支
4、git stash apply 将贮藏的文件重新应用
5、git stash drop 0 移除刚刚贮藏的文件
git stash 指令
git stash list 显示队列
git stash apply [index] 将指定的贮藏的文件重新应用
git stash drop [index] 移除指定贮藏的文件
场景3:
开发分支上有多个commit,本次迭代只需要上其中的某一个commit,需要将这个commit合并到test分支。
解决方案:
1、dev分支git log找到那个commit的SHA-1 校验和 如(62a521)
2、切换到test分支
3、git cherry-pick 62a521