之前也写过一篇git的文章,当时主要写的是关于对小乌龟的操作(时间久远,写的也一般)。但是命令行的控制如果学会了其实是会更加的方便,效率更高,所以这次专门针对git的命令行控制写一篇文章,也可以说是对于上一篇内容的一次重置。

首先推荐一个git学习网站,通过可视化的界面比较直观的展示了各种命令的过程,并且包含了一些本文并不涉及的地方,建议对照本文和网站一同学习效果最佳哦。

操作逻辑和提交流程

操作逻辑

image-20220810020235028

在git中,文件所处的位置分为工作区域、暂存区域、Git仓库三个区域,这三个区域都是独立存在的(可以理解为三个相互独立的文件夹),我们进行git版本控制就是将文件在工作区域修进行增删改后放入暂存区域,当可以形成一次提交后,最终放入git仓库后推送到远端(比如github)的过程。

基本命令

下面介绍了我们对工程文件操作的几个基本命令:

#当我们想要在文件夹中创建一个仓库
git init                    #创建git仓库
#如果是首次使用git则需要对git进行用户名和邮箱的配置(最好与你的github账号一致)
git config --global user.name "username"
git config --global user.email "myemail@email.com"
#当我们完成了第一次对工程的增删改后,想要提交a1.cpp到git仓库让工作区的文件完成版本控制
git status                  #查看当前状态
git add a1.cpp              #将a1.cpp放到暂存区中
git add .                   #可选:将目前所有增删改过的文件加入暂存区,
git commit -m "add a1.cpp"  #将暂存区的所有文件提交到git仓库中并写下"add a1.cpp"的版本描述wq
#当我们完成第一次提交后想要单独删除a1.cpp文件并提交
git rm a1.cpp               #删除a1.cpp,让下一次提交时不纳入版本管理
git commit -m "del a1.cpp"  #将暂存区删除a1.cpp的信息提交到git仓库中并写下"del a1.cpp"的版本描述
#我们已经完成了两次的提交,想要查看我们的历史版本
git log                     #选项说明:oneline(只显示一行,方便查看) decorate(显示分支情况,后面分支管理详细说) all(显示所有分支的信息) graph(图形化的显示)
#我们完成了多次的提交,现在想要push到github或者其他远端上(本文章默认你已经在github上已经创建好仓库了)
git remote add origin 'url' #origin是远端分支名,可以自定义,url为远端仓库地址
git push -u origin master   #第一次提交需要填写,master为git安装时候默认的主分支,一般不变,origin为上一步设置的远端仓库
git push                    #以后提交到远端只需要git push即可提交到远端

在实际开发中,我们可能会遇到下面几种场景:

  • 版本刚刚提交到仓库,发现有两个文件忘记增加了
  • 版本刚刚提交到仓库,发现版本说明写的不太全面
#执行带--amend选项git会更正最近的一次提交
git commit --amend              #会进入一个vim界面,输入i进入插入模式即可对第一行的版本说明进行修改,完成后:wq退出vim
git commit --amend -m "add xx"  #直接在vim外提交

当我们提交后不小心误删了一个叫做a1.txt的文件:

git checkout -- a1.txt          #恢复文件,checkout命令还可以切换分支,后面会详细讲
git checkout HEAD~ a1.txt       #拓展:将当前版本的上一个版本的"a1.txt"拷贝包当前的工作目录和暂存目录中

配置SSH秘钥

git支持https和git两种传输协议,https协议和git协议。如果用https协议,每次pull, push都会提示要输入密码十分麻烦,所以我们一般使用git协议来免去输入密码的麻烦,这里主要专注于如何配置SSH秘钥而不是详细的讲解SSH协议的原理,下面就开始操作吧。

#在这之前要进行email和name的配置,前面基本命令汇总提过就不重复说了
ssh-keygen -t rsa -C “myemail@email.com”    #创建新的SSHkey,可能会让你输入密码,可以不输直接两次Enter
cd ~/.ssh                                   #打开秘钥存放的文件夹
cat id_rsa.pub                              #复制输出的秘钥
#最后一步:复制秘钥,在github网页设置新的SSHkey

文件操作

删除文件

git rm a1.cpp               #删除a1.cpp,让下一次提交时不纳入版本管理
  • 该命令指删除的只是工作目录和暂存区域的文件,也就是取消跟踪,在下次提交时不再纳入版本管理
  • 当工作目录和暂存区域的同一个文件存在不同内容时,执行git rm -f 文件名 可以强制将两个文件都删除
  • 如果只想删除暂存区域的文件(保存工作目录的)那么你可以执行git rm --cached 文件名 来实现

重命名文件

如果直接在目录中重命名文件,可能会造成git以为你是删除了文件a,再新建了文件b,这样会丢失该文件的版本控制,因此使用下面的命令来重命名文件。

git mv a1.txt a2.txt    #将a1.txt重命名为a2.txt
git status              #此时git会提示你进行了一次重命名操作

版本管理

版本回退

image-20220810130442542

如果我们提交的版本有问题,我们常常需要回退版本。首先介绍一个概念,HEAD是一个指针永远指向当前的git仓库的版本,可以通过git reset命令来改变HEAD指针的指向,也就是说git实际上储存了所有提交了的版本的git

下面介绍了版本回退常用的reset命令的操作方法:

git reset --mixed HEAD  #mixed为默认选项,移动HEAD的指向到上一个快照,将HEAD移动后指向的快照回滚到暂存区域,也就是说相当于重置了add的操作
git reset --soft HEAD~  #移动HEAD的指向上一个快照,不对工作区和暂存区做任何操作
git reset --hard HEAD~  #危险操作,如果当前没有commit的文件会被删除,移动HEAD的指向到上一个快照,将HEAD移动后指向的快照回滚到暂存区域,将暂存区域的文件还原到工作目录(会将工作区真实的修改回)
git reset HEAD~         #回退到上一个版本(mixed)
git reset HEAD~~        #回退到上上个版本
git reset HEAD~10       #回退到上10个版本
git reset a534c         #回滚到指定的版本,写git log中commit处的hash值中的前几位
git reset HEAD~ a.txt   #回退a.txt文件的版本到上一个版本
#如果想要reset后想要回滚到未来的某个版本
git reflog              #找到对应版本的hash值再git reset回滚到对应版本

版本对比

git diff                    #比较暂存区与工作区的不同
git diff 453f932 31d0950    #比较两个指定版本的不同
git diff 453f932            #比较当前工作目录和指定版本的不同
git diff -cached 453f932    #比较暂存区域和git仓库快照,hashkey不写就是与最新提交的比较

image-20220810205137778

分支管理

当你的项目已经开发到某一个阶段,想要开发一个新的功能,但不想影响主分支上的项目运行,这时候就需要新建一个独立的分支,等待开发完成,进行调试后最终合并到master主分支中。

image-20220810221547799

我们想要做的第一件事情就是创建和切换分支,下面介绍了对应的命令:

git branch feature      #创建分支“feature”为分支名
git log --decorate      #查看当前的分支情况(HEAD指向的分支就是当前分支)
git checkout feature    #切换到"feature"分支
git log --decorate      #此时就可以看到HEAD指向的改变
#接下来就可以在新的分支下进行功能的开发和提交了

当我们完成了开发和提交,接下来要做的就是合并分支了:

git checkout master     #首先切换回主分支
git merge feature       #将"feature"分支合并到主分支
#如果有文件在当前分支和被合并的分支上都有修改,就会出现”冲突“
#提示:Merge conflict in a3.txt Automatic merge failed; fix conflicts and then commit the result.
#出现这种情况就需要我们手动打开冲突的文件修改成我们想要的结果(冲突的文件会有特殊的标记,方便我们解决冲突)
#当我们完成修复并add、commit后就完成了分支的合并
#当然如果两个分支没有出现冲突,那么直接就可以完成自动的分支合并,不需要额外的提交

#另外还有一种合并分支的命令叫做git rebase
#Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用Rebase 的话,代码库的提交历史将会变得异常清晰。
git rebase main         #具体的操作可以参考最上面的学习网站,另外可以在网站中了解到rebase -i的操作

如果我们想要删除一个分支:

git branch -d feature   #删除分支"feature"

如果你想要切换到一一个分支中做实验,而不是真的创建一个分支,这时候就可以使用匿名分支:

git checkout HEAD~      #在当前分支的当前版本的上一个版本建设一个匿名分支
#如果在匿名分支上完成了提交后切换为别的分支,git会提示你要不要把通过"git branch <new-branch-name> 178d909"将匿名分支转换成一个一般的分支

远程仓库

我们使用git一般都会涉及到团队合作,这就一定会使用到远程仓库,下面介绍几个远程仓库中常用的命令:

git clone            #本地创建一个远程仓库的拷贝
git fetch            #实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态,并不会改变你本地仓库的状态。它不会更新你的 main 分支,也不会修改你磁盘上的文件,可以理解为下载。
git pull             #实际上就是git fetch+git merge的缩写
git pull --rebase    #实际上是git fetch+ git rebase的缩写
git push             #将变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录

参考资料

https://www.bilibili.com/video/BV1Vs411876L

http://t.csdn.cn/WrceT

https://blog.csdn.net/xueyijin/article/details/111464439

https://blog.csdn.net/weixin_47456202/article/details/115617792

https://www.jianshu.com/p/e57a4a2cf077

https://blog.csdn.net/qq_38721302/article/details/113283406

https://learngitbranching.js.org/?locale=zh_CN