Skip to main content
  1. Posts/

Git查漏补缺

·2 分钟

git体系 #

git
由上图可以看出,git主要由两部分组成,一个是远端仓库,一个是本地仓库。 本地仓库又由一下几个部分组成:

  • 工作区:就是我们平时写代码的地方,比如我最常用的就是vscode
  • 暂存区:我们运行git add命令时,代码就会被推到暂存区,起到一个缓存的作用,同时也能帮Git在做diff的时候提高查找性能
  • 本地分支:运行git commit命令后,代码就被提交到本地分支上了,可以在本地.git目录下的refs/heads目录中查看到本地的分支代码信息
  • 远端分支本地副本:执行pull、fetch、push指令时都会往这里更新,它是远程仓库各分支数据在本地的一个副本,.git文件下的refs/remotes目录可以查看到具体信息

git工作流程 #

日常工作中,我们常用流程大概是这样:

在github上建一个新的远程库,或者远程库中已经有数据了

git init #

这时本地还没有库,我们先用git init命令初始化一个git仓库

现在远程、本地都有仓库了,但是二者没有任何关联,将他们联系起来有两种情况

git remote #

如果远程仓库是新建的,没有任何数据,我们需要使用git remote add origin xxx.git添加一个远程版本库到本地, 相应的git remote rm命令是删除远程版本库关联。

然后使用git push -u origin master把当前仓库的master分支和远端仓库的master分支关联起来,这样后续我们push或者pull的时候就可以直接输git push/pull,而不是git push\pull origin master

git push后面的-u是什么意思 #

git push加一个-u参数,其实就相当于给本地分支定义一个上游分支,让git知道当前操作的是哪条分支。 相当于同时执行了git push origin mastergit branch --set-upstream master origin/master 如果一开始没有代入这个参数,直接运行git pull指令时,会出现以下报错

git_pull_wrong
大概意思是没找到当前分支

git clone #

如果远程库已经有数据了,可以直接在本地库使用git clone xxx.git命令将远程库克隆到本地

这时我们默认是在master分支上

当我们在上面的命令行后添加参数git clone xxx.git -b branch时,会自动给我切换到branch分支上

git branch #

关于分支的操作有这些:

  • git branch:查看本地所有分支信息
  • git branch -r:查看远程仓库所有分支
  • git branch -a:查看本地和远程仓库所有分支

git checkout #

如果我们想以当前分支为基准创建一个新的本地分支并切换过去,可以使用git checkout -b branch1命令, 它其实是两个命令合并而成的:git branch branch1创建分支,git checkout branch1切换到该分支上。

git add #

当我们在工作区吭哧吭哧敲完代码,根据流程,我们得先把代码添加到暂存区,就需要用到git add命令了

  • 我们可以一个一个文件添加到暂存区:git add [filename1] [filename2] ...
  • 或者把当前目录下所有文件改动都一口气添加到暂存区:git add .
  • 又或者直接把仓库里所有文件改动都添加到暂存区:git add -A

git commit #

然后我们就需要把代码推到本地分支上去了:git commit [filename1] ... -m [mesaage] 这个命令有两个参数:

  • -m:后面跟的是本次提交的相关信息,可以简单地描述一下本次提交代码做了哪些改动,添加了什么功能
  • -a:对于已经被commit提交过的代码,这个命令相当于执行了git add -A,不需要另外再add一遍了; 对于没有被提交过的文件,还是需要add后才能被commit到本地分支上去

一般工作中更多的是使用git commit -m 'do sth'这个命令,也可以使用git commit -am命令,相当于同时执行了git addgit commit

git rm #

有添加就有删除,当我们不小心把不需要提交的文件提交到本地仓库了,可以使用git rm [filename]将其删除。

git rm -r dist可以直接删除一个目录。

git push #

接下来就要正是把代码推送到远程仓库里去了。

如果我们至始至终都在master分支上工作,并且之前初始化本地仓库时运行了git push -u origin master命令,现在只需要输入git push指令就ok了。

如果我们是要将本地创建的分支推送到远端,就需要使用git push --set-upstream origin branch1将分支推上去并关联起来。

有没有觉得这行代码很熟悉?上面git pull的报错图推荐的指令是git branch --set-upstream-to=origin/<branch> test,就是将本地分支和远程分支关联起来。

如果远程仓库中已经有了这个分支时,本地代码没有和远程代码冲突的情况下会直接将本地改动提交上去;

如果出现冲突,就会提示你先把远端分支中的代码pull下来解决冲突,然后再推上去。

git pull #

当本地分支和远端分支已经建立联系了,我们只需要git pull就能把代码拉到本地,但如果出现上面的情况,

两端没能建立联系,就需要使用git pull origin branch1拉取指定的远端分支到本地分支。

冲突解决后再运行git push --set-upstream origin branch1

git fetch #

当远端仓库对应分支的代码有了新的变更,而当前工作区的代码还没有修改完成,就可使用git fetch将远端代码先拉到本地仓库

git merge #

等本地代码写完并提交到本地仓库了,需要合并一下远端分支的更改,就可使用git merge origin/[branchname]。 也可以将指定分支的代码合并到当前分支:

  1. git checkout master切换到master分支,git pull拉取最新代码
  2. 切回开发分支,执行git merge master合并master代码到开发分支中 和上面的代码实现的效果是一样的,只是所有修改都在开发分支里了,master分支上并没有我们提交的修改。 等修改测试后没有问题可以上线了,再切换到master分支,用git merge origin/[branch1]把分支合并到主分支上,然后git push origin master

git log #

提交代码后都可以通过这个指令看到提交记录,这个主要是用来进行代码版本的回滚等操作的

git reset #

这个指令后面跟着一个参数和一个版本信息。 在你查看git log的时候,会有一行信息大概长这样

commit e55c4d273141edff401cbc6642fe21e14681c258 (HEAD -> branch1, origin/branch1)

commit后面这一串数字就是这个版本信息,一般都很长,我们可以只复制前7位。 git reset有三个参数:

  • --soft:如果你已经将改动commit到本地仓库,git reset --soft e55c4d2可以让本地仓库的内容回到e55c4d2这一次提交,但暂存区和工作区的内容还在
  • --mixed:默认参数,暂存区的内容也会回到指定回滚的版本,工作区的改动还在
  • --hard:直接连工作区的代码都回滚到指定版本,之前所有改动都没有了

git relog #

当你reset之后,在看git log会发现,回滚版本后的所有提交历史都不见了,最新提交记录就是你此时回滚到的版本。 但你发现之后的代码提交中有一部分你依然需要,就可以使用git relog看到所有的操作记录了,然后就可以CV需要的代码了。

git revert #

这是一个温和版的reset。 reset相当于时间穿越,让你穿越到指定的提交,所以git log看不到reset版本后的记录; 而resvet是产生一个新的提交,把你改动的代码都恢复到指定版本的样子。

git cherry-pick #

一个不常用,但可以救人于水火的功能。 我是小白的时候,在修改代码时总是会忘记切换分支,直接就在master上改了,如果代码已经被commit到本地仓库,就可以git log查看提交记录,复制本应该在分支上提交的commitId,如果有多个提交就全都复制下来,然后切换到需要修改的分支上,使用git cherry-pick master commitId1 commitId2 ...指令。 之后别忘了在master分支上用reset或者revert回滚一下代码。

git tag #

如果一个项目一直有人维护、更新迭代,就会给它打上标签标注版本。 标签有两种:轻量标签和附注标签

轻量标签 #

创建指令:git tag v1.0.0 一旦创建了标签,就基于当前分支创建了一个不可变的分支,当你切换到这个分支并做任何修改并提交,都无法在分支历史中找到记录,它会帮你生成一个独立提交,commitId可以在如图左下角查看到

git
你可以通过commitId切换到本次提交,如果需要保留当前提交,可以使用git switch -c <new-branch-name>创建一个新分支, 否则直接git switch -丢弃这次提交。

附注标签 #

创建指令:git tag -a v1.0.1 -m "发布正式版 1.0.1" 比轻量标签多了两个参数,同时也能保留更多信息,它是存储在Git数据库中的一个完整对象。 git show可以看到标签信息。

推送标签 #

git push origin tagName 创建完标签就能把它推送到远端了。

其它命令 #

  • git tag:查看标签
  • git tag -l v1.0.1:筛选标签
  • git tag -d v1.0.1:删除本地标签
  • git push origin --delete v1.0.2:删除远程标签

git rebase #

rebase常常会和merge作比较,从字面意义上看,rebase就是改变基准库。 假设有两个分支,一个master,一个feature

rebase1
由上图可以看出feature是基于master分支的B节点创建的,之后,在master分支上有一个新提交M,而feature上有两个新提交,C和D。 当我们输入以下指令

git checkout feature
git rebase master

提交节点就变成了这样

rebase2
feature的基底变成了M节点,并且feature上的提交合并到了新基底后面。 如果在rebase时,master分支上没有新提交,那么就不存在换基,效果跟merge就一样了,只是merge指令会多一条记录merge操作的提交记录。 实际工作中建议还是使用merge,因为日志会把每一次提交都记录下来,而rebase会让日志呈线性显示,无法得知最初支线是从哪个节点拉取出来的。

stash #

最后说一个特殊区域,git本地除了工作区、暂存区和本地分支外,还有个储存区。 一般我使用它的场景是, 在一个分支工作了一会,突然需要切换到另一个分支上去,又不好把未完成的代码推上去, 就先git stash把变更保存在本地, 等另一个分支的问题解决之后,切换到之前的分支git stash pop把最新stash的更改加回来。 但并不是很推荐这样用,因为一旦忘记就麻烦了。

常用命令 #

  • git stash save 'xxx':存储变更,如果直接git stash会自动分配储存记录标记
  • git stash list:查看储存区的所有提交列表
  • git stash pop:弹出并引用最近一次存储区的代码提交
  • git stash drop stash@{n}:删除某次储存记录
  • git stash clear:清除所有stash信息

参考文章 #

  1. 《Git体系介绍+常用命令及其应用场景》
  2. 《git中push -u是什么意思》
  3. 《git rebase详解(图解+最简单示例,一次就懂)》