由于之前使用svn,最近改用git,虽然也用过一段时间git,但之前大部分时候都是在单人使用github,因此在这里好好学习一下git的相关操作,并对git的操作进行总结.
之前用过svn的可以参考此段.
此表格出处
在表格中我们看到Git是分布式版本控制系统,而svn是集中式,我们可能会奇怪,svn我们也是多人在不同的电脑上协作啊,但是理解了两者的区别,我们就会发现,svn只有一个中央库,存放在中央服务器中,而git有多个仓库,我们每个人都有自己的个人仓库,也可以创建多个分支.
我们可以这样理解:svn有一个中央库,我们的一切操作都要和svn的中央库挂钩,当我们没有网络了,我们无法提交,也无法查看日志,我们做的一切都服务于svn中央库,而git我们每个人都有自己的库,即使没有网络,我们也可以提交,可以回滚,可以查看日志,当我们想和远程库进行操作的时候,只需要push即可,远程库相当于一个媒介,帮助我们和别人进行沟通交流,但没有远程库,我们自己也可以使用git进行版本控制
svn和git的操作也有不同:
svn 我们想提交的时候,add 新文件(此步骤可以放在后面的解决冲突处执行),然后需要pull最新代码,然后本地解决冲突,然后commit
git 我们提交的时候,add(和svn不同,新文件和修改的文件都需要add操作),然后commit,然后
然后pull,然后解决冲突,最后push
svn每一次提交都要解决冲突,而git只有我们push的时候或者合并分支的时候才需要解决冲突(单一分支操作),对于git我们可以将一个功能的每一次修改都commit一次而无需解决冲突,直到整个功能开发完成,我们再进行最终的push,这里面深层次的原因就是svn的提交是和服务器交互,而git的提交时本地的i行为,push才是和服务器交互
新增文件不在四个区当中 | add—>暂存区 |
---|---|
工作区 | add—>暂存区 |
暂存区 | commit–>本地仓库 |
本地仓库 | push—>远程仓库 |
远程仓库 |
下面介绍一个git的完整的提交操作流程
1.git add . //(.或者根据文件add) 此步骤的目的是为了将我们想要的文件添加到暂存区
2.git commit -m commit的内容 //此处我们提交了一个版本,版本提交到本地的版本库中
3.git stash //比如说我们同时开发两个功能,现在我们另一个功能还没做完,只想提交一个功能,怎么办?使用git stash命令,将未提交的代码或者不想提交暂时存放起来(注意:这些代码不在暂存区),此时工作区的代码和暂存区的代码都会被隐藏起来(注:新增的文件也想隐藏需要使用git stash -u)
4.git pull
5.解决冲突,此时如果产生冲突需要我们再提交一份解决冲突的版本
6.git push //此时推送远端成功,push的是 提交版本+解决冲突版本
7.git stash pop //将刚刚隐藏的提交的文件恢复出来
8.继续解决冲突
9.开始我们的工作
此处以操作介绍命令,而第5章节将单独介绍命令,4,5章节可能会包含重复内容
git clone 远程库地址
1.git remote add origin 远程仓库地址 //和线上仓库地址做关联
2.git pull 或者 git remote update origin --prune // 这一步仅仅是为了获得远程仓库的分支,很多方法
3.git branch --set-upstream-to=origin/main(此处main填写远程的分支名) //将远程分支和本地当前分支绑定起来
4.git pull/push
git remote update origin --prune //刷新远程仓库的分支,如果远程仓库新建分支, 需要使用这条指令
git remote rm origin //此步骤是为了解除远程仓库的联系
git remote -v //查看远程仓库的地址
git branch -a //查看项目的分支, -a代表全部,包括了本地和远程
此图为和线上仓库关联起来,最后的两条指令表示我们连接了远程仓库,但是并没有获得远程分支
此图为 git pull指令的结果,之所以实行这一步是为了查到线上有几个分支,当然还有其他的办法
1.修改文件
2.git add . //此处提交文件到暂存区,可以提交多个,也可以提交一个
3.git commit -m 此处添加更新的备注 //此处提交文件到本地仓库
4.git push //此处提交文件到远程仓库
git提交需要注意
git新增文件的操作和git修改文件的操作相同
,没有任何多余的其他步骤
git提交的时候只会提交暂存区的文件
附1: git add
在使用svn的时候,我们使用新增文件的时候 需要先add文件后提交,而更新的文件只需要commit即可
而在git当中,新增的文件git也默认添加了,但是新增和修改的文件都需要 add 添加到暂存区这一步骤
附2: Untracked files:
git untracked files 实际上就是新增的文件,当我们使用add的时候,它会直接提交到暂存区,此处一定要记住和svn新增文件的不同之处
使用git status 和git status -s 我们可以看到git 文件的状态
附3:git reset
git reset 可以将我们提交到暂存区的文件重新返回去
修改--->add--->commit
修改--->add--->commit
git push //此时我们直接push两次commit,远端可以看到两次的日志
此时pull失败,有两种普遍的解决方法,当然commit和stash也可以结合使用:
git stash //此种stash只会暂存 修改和暂存区文件 不会暂存新增文件
git pull
git stash pop stash@{0} //取出不删除
或者 git stash pop //取出并删除
有时候有新增文件,但是stash只暂存暂时修改的文件怎么办?
git stash -u 或者 先add,再stash
git commit -m 本地提交
git pull //此处进入 (main|MERGING),下面是两种解决冲突的方法
1.git merge --abort (此种方法是返回到冲突之前的情况当中,就是咱们pull前的情况)
2.修改文件 ,解决冲突
git add .
git commit -m 解决冲突
git push //这样会多提交一个解决冲突的版本
初学的时候,经常会无意的将自己的一些重要信息上传到github上去,比如说最常见的数据库的地址和密码,如果被别人发现,很容易出现问题,即使我们提交一份新的代码,但是还是能从github上面的提交记录中看到我们曾经暴露的信息
下面讲一下我们删除github上面的提交记录
参考网址:github怎样清除历史提交,保留最新提交
1、git clone [URL] 克隆git仓库
cd [仓库名] 进入git仓库
2、git checkout --orphan new_branch 创建一个名为new_branch新的空的分支
3、git add -A 添加所有文件到new_branch分支
git commit -am '提交信息' 对new_branch分支做一次提交
4、git branch -D master 删除master分支
5、git branch -m master 将当前所在的new_branch分支重命名为master
6、git push origin master --force 将更改强制推送到github仓库
git log 查看提交的版本号 //查看准备回退的版本
git reset (--hard/--soft/不加参数(mixed) )版本号 //本地回退版本
git push --force //提交
此种方法就是将我们的版本回退到提交敏感信息之前的那个版本,这样我们删除敏感信息,再次提交就可以了
--hard 模式,回退指定版本号,同时清除我们本地的所有修改,清除指定版本号之后的所有修改
--soft 模式,回退版本号,同时将本地的所有修改和版本号之后的所有修改全部退回到工作区/和未追踪(add+commit)
--mixed模式,回退版本号,将版本号之后的所有修改回退到暂存区(可以直接commit)
前面几种都或多或少有问题,下面这种方法是最好的办法,我们使用
1.git rebase -i HEAD~2 //此种方法选择的是近三次提交
2.git rebase -i commit版本号 //此种选择的是该版本之后的所有版本
上面两种方式选择任一种,就会进入rebase--界面 类似于:
pick 34699ae 提交1 最旧
pick 37f6884 提交2
pick ca09187 提交3 最新
此时,我们修改一下,修改成:
pick 34699ae 提交1
d 37f6884 提交2
pick ca09187 提交3
简单说我们抛弃哪个版本就在前面加上 d 即可
保存之后,继续使用 git push --force即可
因为我们要做的是删除提交记录,不再像push提交,即使提交错误,我们也可以通过回滚版本解决问题,因此做上面这些操作的时候一定要小心,可以使用新建分支做一下备份,这样操作失误依然有机会挽救
git merge常用的三种模式,其中有两种经常被使用
这两种,首先在merge的时候两个分支都有提交时候是没有区别的,但是有一种情况出现:
我们在A分支合并B分支的时候,A分支我们没有提交,但是B分支提交了,此时会出现差别,
–ff这种命令会直接移动指针,将B分支提交的东西,都归于A分支
–no-ff这种命令会保留B分支的提交记录,产生一个新的提交
当使用第一种方法的时候,提交记录是一条直线,使用第二种方法的时候会产生分支
一般日常工作中,merge默认的是-ff这种,但是很多时候我们推荐使用 --no-ff,因为这种命令可以让我们清楚的看到记录哪个分支提交,另外此命令回退的时候,我们不会回退分支提交的记录(因为个人的分支可能会提交很多次),而是回退主分支的记录
git branch dev1 //git创建分支
git checkout dev1 //git修改分支
1.选择commit
git rebase -i HEAD~2
后面的数字代表着最新的几个版本git rebase -i commitId
表示该版本号(不包含本版本)之后提交的所有版本squash
了pick 34699ae 提交1
pick 37f6884 提交2
pick ca09187 提交3
#######################################################################
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
3.编辑好之后,:wq
进入编辑注释的页面编辑commit注释,或者进入解决冲突的界面解决冲突
先看使用场景,比如说我们本次提交了aa.txt,bb.txt,突然发现还有cc.txt没提交,此时我们的办法是什么?
当然下面我们介绍另一种方法:
1.将cc.txt提交到暂存区
2.使用 git commit --amend //此方法类似于补丁,将暂存区的文件直接合并到最新一次提交
3.当然上面可以编辑commit的注释,使用 git commit --amend --no-edit可以直接提交
git log --oneline --graph --decorate --all
git reset [ –soft | –mixed | –hard]
reset–hard模式:将我们的代码回退当相应的版本,同时清空工作区,暂存区以及回退版本之后提交的所有代码,如果你有新的文件,但是没有提交到暂存区,依然存在(实际这代表着新文件没有被git控制)
简单一点理解,reset和reset --soft都意味者你的操作不会被清除,这里面包括 你修改的文件,你新增的文件,你add之后暂存的文件,以及你回退版本之后又提交上去的文件,两者的区别只是这些文件存放的位置
–soft意味着你本次的操作不动,曾经提交的记录进入暂存区
–mixed意味着你本次的提交到暂存区的文件和你曾经提交的进入暂存区的文件再次退一步,退回到工作区或者Untracked files
将提交的文件退回到暂存区,此时只要我们再次commit就可以提交
当我们想要撤销暂存区的一个文件或者一批文件,该怎么操作?
git reset
撤销暂存区
git reset 文件名
从暂存区退回单个文件
看一下本质,实际上使用我们还是再使用 git reset指令,只是版本号默认成为了最新的版本号
再试一下 git reset --hard
我们的工作区,暂存区文件都被清理了,而git reset --soft
呢,git的状态没有发生任何改变
hard模式需要我们谨慎使用,简单来说hard模式会把我们 提交的,暂存区,工作区全部清空
mixed,soft都会保留我们的工作信息,但是不同的是soft会将曾经提交的文件放到暂存区,mixed在此基础上清空暂存区