git HEAD理解和使用

git HEAD理解和使用

理解HEAD是迈入git高级的门槛,具有非常重要的意义。本文介绍了git中HEAD相关概念,然后从HEAD的角度出发,对一些常见的git指令进行了解读。

分支和HEAD和指针

  1. HEAD的本质 是指向某个commit对象的指针
  2. 分支指针的本质 是指向某个commit对象的指针
  3. 补充分支指针和分支的概念。分支是git库中众多commit对象的组织方式 ,所以分支又可以看成是commit对象链表 。而分支指针则指向这个链表的尾部。借用C语言中的知识,可以用分支指针完全表示这个commit链表,所以分支指针就是分支(正如int a[] = {1,2,3};中的a的含义一样)。
  4. 所以HEAD的本质和分支指针的本质是相同的。
  5. 那么它们之间有什么关系呢?分支指针指向的是所在分支最新提交 产生的commit对象;而HEAD指向的是某一个分支最新提交 产生的commit对象。也就是说HEAD肯定是 分支指针,而只有被激活的分支(或者称为"当前分支")的分支指针才可以被称为是HEAD。
  6. 用程序的方式来理解: // 创建三个分支a,b,c int a[] = {1,2,3}; int b[] = {4,5,6}; int c[] = {7,8,9}; // HEAD,也就是p,在a分支上,表示当前分支为a int *p = a; // 切换到了b分支上, HEAD指向b p = b; // HEAD切换到了c分支上, HEAD指向c p = c; // 分支指针是不可以移动的,但是HEAD可以 // c++ Error p++ // 表示HEAD指向了c分支上不同的commit对象
c++ 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    int a[] = {1,2,3};
    int b[] = {4,5,6};
    int c[] = {7,8,9};

    int* p = a; // 指向a分支的起始位置

    printf("%d\n", *p); // 输出a分支的第一个元素

    p = b; // 切换到b分支,将指针p指向b分支的起始位置
    printf("%d\n", *p); // 输出b分支的第一个元素

    p = c; // 切换到c分支,将指针p指向c分支的起始位置
    printf("%d\n", *p); // 输出c分支的第一个元素

    // 分支指针是不可以移动的,但是HEAD可以,这里涉及到指针运算
    // c++;
    p++; // HEAD指向了c分支上其他commit对象
    printf("%d\n", *p);
    getchar();
    return 0;
}

HEAD表达式

  • HEAD 指向当前分支最新的提交。
  • HEAD~ 等同于 HEAD^,表示当前提交的父提交。
  • HEAD^ 表示当前提交的第一个父提交。
  • HEAD~n 表示当前提交的第 n 代祖先提交。

HEAD相关操作

下面举一些常见的git操作,也许你已经对这些操作了如指掌,但是这次我们从HEAD的角度来理解一下这些操作的含义:

  • 查看当前 HEAD 的位置:使用 git rev-parse HEAD 命令可以查看 HEAD 所指向的提交的 SHA 值。

  • 切换到另一个分支:使用 git checkout branch-name 命令可以切换到另一个分支,并将 HEAD 指针移动到该分支。

  • 创建新分支并切换到该分支:通过 git checkout -b new-branch-name 命令可以在当前 HEAD 所在的提交上创建一个新分支,并立即切换到该分支,对应到上述代码,相当于是int* p = a;

  • 撤销最新的提交:使用 git reset --hard HEAD^ 命令可以撤销最新的提交,并回退到上一个提交状态,之所以有这种效果,在于HEAD~或者HEAD^是HEAD的上一次提交,也就是倒数第二次提交

  • 查看特定文件在 HEAD 版本的内容:使用 git show HEAD:path/to/file 命令可以查看 HEAD 版本中某个文件的具体内容,当然git show HEAD~n:path/to/file也是可以的

  • 检出特定提交:使用 git checkout commit-hash 命令可以将 HEAD 指针移动到特定的提交,以查看该提交的内容或创建一个分离的 HEAD 状态(说人话就是打上tag),这种情况实际上就是上面代码中的p++,虽然分支指针不能移动(正如不能对数组变量进行运算),但是指向分支指针的HEAD可以移动

  • 创建临时分支:通过 git checkout -b temporary-branch-name 命令可以在当前 HEAD 所在的提交上创建一个临时分支,一般来说修改bug的时候会创建临时分支,这种一般称为hotfixes分支

  • 移动 HEAD 到指定分支的最新提交:使用 git checkout branch-namegit pull 命令可以将 HEAD 指针移动到某个特定分支的最新提交,就是上面代码中p从指向a数组变成了指向b或者c数组

  • 查看 HEAD 所在分支的状态:使用 git status 命令可以查看当前 HEAD 所在分支的状态,包括已修改、已暂存和未跟踪的文件。

  • 执行交互式的 rebase 操作:使用 git rebase -i HEAD~n 命令可以执行交互式的变基操作,编辑、合并或重新排序提交;这个代码简单理解成对最近n次提交进行操作,不要和"变基"这么猥琐的词联系起来

  • 创建轻量级标签:通过 git tag tag-name 命令可以创建一个轻量级标签,它只是指向当前 HEAD 指针所在的提交;简单来说就是给当前HEAD指向的commit对象起个别名,并将别名记录下来以便日后使用,一般对于有参考意义的重大commit进行此操作

  • 查看 HEAD 所在分支的提交图形:使用 git log --graph 命令可以以图形化方式展示当前 HEAD 所在分支的提交历史。

  • 检查 HEAD 是否指向某个分支:使用 git symbolic-ref --short HEAD 命令可以确定 HEAD 是否指向一个分支,即返回当前所在的分支的分支名

总结一下:

上述的命令可以大致分成下面几类:

  1. 查看状态类:
  • git rev-parse HEAD
  • git show HEAD:path/to/file
  • git status
  • git log --graph
  • git symbolic-ref --short HEAD
  1. 切换分支类:
  • git checkout branch-name
  • git checkout -b new-branch-name
  • git checkout -b temporary-branch-name
  1. 同分支内移动类:
  • git reset --hard HEAD^
  • git pull
  • git rebase -i HEAD~n
  1. 直接操作commit类:
  • git checkout commit-hash
  • git tag tag-name
相关推荐
GIS程序媛—椰子31 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_00138 分钟前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端41 分钟前
Content Security Policy (CSP)
前端·javascript·面试
木舟100944 分钟前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安1 小时前
前端第二次作业
前端·css·css3
啦啦右一1 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落1 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt