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
相关推荐
sen_shan7 分钟前
Vue3+Vite+TypeScript+Element Plus开发-02.Element Plus安装与配置
前端·javascript·typescript·vue3·element·element plus
疾风铸境19 分钟前
Qt5.14.2+mingw64编译OpenCV3.4.14一次成功记录
前端·webpack·node.js
晓风伴月23 分钟前
Css:overflow: hidden截断条件‌及如何避免截断
前端·css·overflow截断条件
最新资讯动态26 分钟前
使用“一次开发,多端部署”,实现Pura X阔折叠的全新设计
前端
爱泡脚的鸡腿41 分钟前
HTML CSS 第二次笔记
前端·css
axinawang1 小时前
在eclipse中通过git放弃某个版本之前所有的更新
git
灯火不休ᝰ1 小时前
前端处理pdf文件流,展示pdf
前端·pdf
智践行1 小时前
Trae开发实战之转盘小程序
前端·trae
最新资讯动态1 小时前
DialogHub上线OpenHarmony开源社区,高效开发鸿蒙应用弹窗
前端
lvbb661 小时前
框架修改思路
前端·javascript·vue.js