返回

必须得会的git

Git看样子应该成为程序员的必修课了。Git可能是非常繁琐而又复杂的东西,但是实际上可能有几个比较核心的功能理解会好很多。

一些参考资料和教程

https://learngitbranching.js.org/?locale=zh_CN 极力推荐

https://git-scm.com/book/zh/v2 官方教程

1、什么是Git

Git是用来做项目管理的,显然,相较于每个人带个U盘拷贝来拷贝去,通过一种有效的方式进行版本管理是更加合理的。Git因此而生,相较于集中化的版本管理,Git这种分布式的管理方案在一个系统崩掉时仍能保证使用,同时还可以保证更加方便的管理。

首先要了解的是,Git的设计逻辑,通常的一些备份工具是通过基于差异的方式用来记录的,但是Git在进行管理的时候,由于项目过于复杂,可能会导致差异较多,每次切换分支导致加载时间较长,从而带来较差的体验,因此Git是采用快照的方式进行版本管理(所以在有些项目会出现.git文件爆炸的情况,源代码量可能少于.git)

接下来第二个重要的事情,Git所存在的状态:

工作区、暂存区以及 Git 目录。
工作区、暂存区以及 Git 目录。

Git存在三个状态,工作目录暂存区Git仓库。这个状态与之后要了解的三个指令息息相关:git commit, git stash, git checkout。在编辑代码时,代码状态是工作目录状态,在进行commit操作进行提交时,会把当前工作目录的状态提交到repo中,此时存在一个commit记录和本地的状态(当然两个内容目前来看是一样的)。但是有时候我们想要测试别分支的内容但是又不想提交目前的代码状态,这时候就可以使用git stash将代码提交到暂存目录方便后续重新取出(当然,相较于commit操作,stash操作用的会相对少一点)

2、如何操作头指针

头指针这个概念似乎不会很频繁的提到,或者当谈到Git的分支时,大家可能更清楚master、main、origin而不知道头指针是什么。

在了解头指针的时候,首先需要知道提交分支的区别。提到的话就很好理解了,前者就是分支每一次git commit得到的内容,后者则是一条指明的轨迹。

头指针可以理解成是用户目前的工作目录的状态,通过git checkout可以非常方便的在不同提交记录之间进行切换(同时本地的代码也会恢复到对应的提交记录),从而查看不同版本的代码状态,同时可以用来在之前的提交状态上进行分支等操作。但是这里着重强调区分头指针、提交、分支之间的区别,这在之后会有一些比较实用的操作(当然我还是觉得git checkout一招鲜吃遍天)

3、如何提交和恢复

首先不讨论暂存的相关问题,因为使用git最重要的几点操作就是进行编辑并且提交保存。最简单的操作就是git add .; git commit了。在使用过程中通常会使用-m参数来描述更改的内容git commit -m "xxx"通过该操作就可以轻松的将修改后的内容保存到Git仓库中。

完成提交之后有时候觉得提交不合适想要恢复,这时候可以做的操作就很多了:

  • 使用git log查看提交记录,之后使用git checkout xxx分离头指针到你需要的位置,这个操作实际上严格意义上属于分支操作,但是可以用在各个地方(所以要被删了楽)(感觉还是checkout走天下
  • 使用git revert HEAD,这个是提交一个新的记录来覆盖之前的记录
  • 使用git reset HEAD,这个则是彻底删除上一次的提交记录(但是由于算是彻底删除所以建议谨慎使用)

因为前面提到了头指针的作用,所以理论上后两条指令可以在任何提交记录上进行使用。

4、分支操作

由于git checkout集成了太多功能了,实际上仅靠git checkout就可以轻松的实现分支的创建(之后被删掉应该就不一样了)。分支的创建倒是一点都不复杂:

  • git checkout -b XXX直接创建XXX分支并切换到对应的分支上(-b表示切换到)
  • git branch XXX创建XXX分支

完成分支创建并把HEAD指针指向对应的分支之后就可以在新的分支上进行修改和提交了。但是这个似乎不是最难的。

接下来要做的是合并分支

合并分支有两种方式

  • git merge XXX操作,该指令将XXX合并到HEAD指针处,注意是合并到指针处,因此可以乱进行merge操作
  • git rebase XXX操作,该指令将当前的HEAD指针通过查找和XXX最近的父节点,把修改线性的添加到XXX上,通过这种方式进行的合并操作,XXX分支仍然在之前的位置,因此需要使用rebase、merge、checkout等恢复到最新的地方。或者使用git rebase A B把A分支的内容提交到B上

知道上述的操作就可以随便进行git的分支操作了。但是上述的操作仅限于本地的一些分支操作,而且不能处理相对复杂一点的情况。

5、远程分支控制

git clone, git push这些都不用说明了。远程操作主要有三个:如何拉取,如何解决冲突和如何提交。

首先是拉取的问题,拉取有两种方式:

  • git fetch直接拉取服务器所有分支的改变(注意头指针不变)
  • git fetch; git merge origin/XXX或者git pull

拉取倒是难度不大,但是Git最困难的一点莫过于在修改过程中远程分支也出现了更改,此时进行git push操作就会显示被拒绝,这种情况下通常需要先git fetch之后在本地进行合并操作(合并操作可以仿照前面的git mergegit rebase),也可以使用git pull。完成修改之后使用git push即可

**但是!**实际上如果尝试修改别人的分支的话,会提示denied,正确的提交方法应该是提交pull request,具体操作如下:

  • git reset --hard o/main 恢复main到远程分支
  • git checkout -b newfeature CX 为提交CX创建新分支
  • git push origin newfeature

说到git push操作的参数origin,这个指的是将本地的分支提交到服务器端的远程分支(默认没有说),但是这个参数实际上是可以指定的(感觉还是指定一下会比较好):

  • git push origin source:dest

对应的git fetch也可以添加参数

  • git fetch origin source:dest注意的是这里的source指的是服务器端,dest指的是本地端

如果两个参数不指明source,则是删除本地或者服务器端对应的分支

6 、自由随意的操作分支

自由操作的话涉及到两个指令:

  • git cherry-pick X1 X2 X3这个指令把X1,X2,X3提交依次添加到当前的HEAD分支上
  • git rebase -i XXX该指令添加了-i,表示交互式的通过查找当前的HEAD指针和XXX最近的父节点中间的操作,把交互的操作线性的添加到XXX上

实际上咱也不会遇到这么复杂切换分支的情况,但是知道总比不知道好一点。

7、有意思的操作

7.1 查看日志

查看日志还是相当重要的其中有如下命令都可以详细的查看git日志和状态:

  • git log

  • git blame

  • git show

  • onefetch

7.2 GUI工具

https://wiki.archlinux.org/title/git

7.3 楽

image-20240312202937406
image-20240312202937406

Licensed under CC BY-NC-SA 4.0