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
相关推荐
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
mosquito_lover17 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
柴柴的小记9 小时前
前端vue引入特殊字体不生效
前端·javascript·vue.js
柠檬豆腐脑9 小时前
从前端到全栈:新闻管理系统及多个应用端展示
前端·全栈
bin915310 小时前
DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)
前端·javascript·vue.js·ecmascript·deepseek