git防遗忘指南-checkout的本质

前言

你是否在一次提交后,想要撤回对应的内容迷茫无措...

你是否在多个分支来回切换开发中,对需要合并散落在不同分支的commit而束手无策...

你是否经常听到同事在说使用rebase命令而根据自己多年的add/commit经验不知道rebase是个什么...

你是否每次跟远端同步都在害怕产生冲突...

你是否对一堆修改想要分步提交而望而却步...

以上的种种,我都有过,在团队开发中,版本管理工具是必不可少的,git也是一个非常常用的版本管理工具,往往速成上手,在网上学习过了怎么提交,推送,拉取,合并操作后,就可以在项目中进行合作了,一般情况下也都适用了,但是git的强大远不止于此,除了递增式的去向前推进commit记录,还可以针对已经提交过的进行选择性的修改,这样妈妈再也不用担心提交后想要修改,还得将文件对着之前的版本,一行一行的改回去了

从这里开始进入正文

分支切换

在使用中,我们知道git鼓励是使用多分支进行开发,通过简单的checkout -b指令就可以新建一个分支,并将当前分支指向新的分支,那么什么是当前分支,新建一个分支是将当前分支的所有内容全部拷贝了一遍么

实际上git的版本控制就是在文件内的./git文件中,里面没有没有对实际需要管理的文件进行一次复制,不同的分支也仅仅是一个引用的指向


git管理的实际内容.png

简单的新建了一个本地仓库,新建了一个文件和master分支,进行一次提交,再切换出develop分支,修改文件后,在develop分支进行一次修改提交,通过git log 查看记录

//每一次的提交都会有一个hash值作为索引标识
commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e (HEAD -> develop) //括号内的就是分支引用的信息
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1  //每次commit需要写入本次提交的修改简介

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255 (master)
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

从这简单的操作可以看出,当前master分支是指向了f1f90f这一次提交,而当前的分支通过HEAD指向,可以看出当前的分支是在develop分支上,并且develop比master分支有一个更新的提交

这个时候切回master分支

//HEAD引用指向了master,并且master还是在f1f90f这次提交上
//log查看的是历史,develop分支由于超前于当前位置,所以就看不到对应的信息了
commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255 (HEAD -> master)
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

这样看来,checkout+分支名就是将HEAD的引用指向了对应的分支,这时候查看./git文件夹中的内容可以看出

HEAD : ref: refs/heads/master

develop : 034c5c1db2b4af576e48d6b5f0bad91e599c117e

master :f1f90fef4ba31a240a81adf0c3774ab4bcdc0255

新建分支和切换之前的分支.png

所以具体的分支就是指向了一次具体的commit,而git管理的主要修改内容还是一个个的commit

再将master分支做一次改动提交,后切换到develop分支,分别查看log

//master新增一次commit记录
commit 6e4d4de115cb81750ad1ff943d9efebb9374c064 (HEAD -> master)
Date:   Wed Sep 7 14:55:03 2022 +0800

    master change 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

//切换回到develop分支
commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e (HEAD -> develop)
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

master指向的commit记录不存在在develop的历史commit中,所以在develop分支中查看log是找不到master记录的,log查看当前指针位置到根节点的提交记录


将提交记录分叉.png
--detach

可以看到在checkout指令后跟具体的分支名,HEAD的引用是指向了具体的一个分支,而具体的分支是指向在了一条具体的commit记录,通过checkout --detach指令,可以将HEAD的引用从具体的分支脱离下来,跟分支一样指向具体的一次提交

当前在develop分支上,执行git checkout --detach指令

//可以看到从之前的(HEAD -> develop)变为了(HEAD, develop)
commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e (HEAD, develop)
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

可以看到HEAD指针的引用从指向develop分支变成了指向对应的commit

这会查看./git文件夹中的HEAD文件内容也就变成了 “034c5c1db2b4af576e48d6b5f0bad91e599c117e”

detach从分支上脱离.png

除了detach可以直接从分支脱离,也可以通过git checkout + commitId 去直接指向一个具体的commit

直接将checkout 到之前master的那一次提交 git checkout 6e4d4d

这样的查看log

//HEAD指针就指向了之前master所在分支的最新提交,并且没有引用master分支
commit 6e4d4de115cb81750ad1ff943d9efebb9374c064 (HEAD, master)
Date:   Wed Sep 7 14:55:03 2022 +0800

    master change 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

通过这一些了的checkout操作,就可以看出git分支的本质就是一个指向具体commit的指针引用,对应的分支信息就是存储的当前分支所在的commit的哈希值,而checkout可以操作HEAD当前工作指针,如果HEAD指向了分支,就会commit提交后跟着分支一起移动,脱钩--detach后,就可以很灵活的从任意一个commit去切换分支,而保持之前的分支引用不变

直接checkout到具体的commit.png

举个例子

在当前情况下,切回develop分支,并产生一次新的提交记录,然后将HEAD指向前一个commit

//step1 git checkout develop 后新增一次新的commit
commit 739ec5bbd9c0ff66a6ba4997ea944bdac4feb7ea (HEAD -> develop)
Date:   Wed Sep 7 22:26:18 2022 +0800

    develop commit 2

commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

//step2 git checkout 034c5c 将当前的HEAD指针指向前一个commit提交
commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e (HEAD)
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

这样就可以从develop分支中的任意一次提交的位置,切出新的分支,进行开发

从HEAD指针的位置切出一个新的分支feature-1,并进行一次提交

//这样就从develop分支的历史记录中牵发出了一个新的分支
commit 4b465a7a3514b65917bbb432902afa5e062a4261 (HEAD -> feature-1)
Date:   Wed Sep 7 22:27:39 2022 +0800

    feature1 commit 1

commit 034c5c1db2b4af576e48d6b5f0bad91e599c117e
Date:   Wed Sep 7 14:02:55 2022 +0800

    develop commit 1

commit f1f90fef4ba31a240a81adf0c3774ab4bcdc0255
Date:   Wed Sep 7 14:00:42 2022 +0800

    first-commit

最终会得到这样的形态的git当前版本示意图

最新状态.png
小结

通过上述一些列的操作,可以理解到git管理的本质就是一次一次的commit提交记录,commit里面有具体的文件的修改记录,分支就是一个指向具体某条commit提交记录的指针,分支的内容也就是对应commit记录的哈希值引用,而HEAD指针可以指向分支随分支一起移动,也可以很灵活的切换到任意的commit

checkout指令的本质就是在移动HEAD指针,并不是在新的分支将文件内容进行一份复制,只是在对应的commit提交节点,增加一个分支的引用关系,这样就让分支的管理变得非常的轻量级,只需要在一个文本文件,记录下一次commit的哈希值,也让操作分支更加的灵活

需要注意的是,本地仓库没有对接远端,如果有远端仓库存在的情况下,远端的分支如 origin/master 也会指向在一个具体的commit提交,如果在本地通过checkout origin/master,跟切换本地分支让HEAD指向对应的分支不同,checkout到远端分支,会让HEAD指针直接指向对应的commit

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容