0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教你20分钟搞懂Git!

电子工程师 来源:lq 2018-12-12 09:48 次阅读

Git 是最流行的版本管理工具,也是程序员必备的技能之一。本文就来教你20 分钟搞懂 Git!

以下为译文:

尽管每天你都会用到Git,但也有可能搞不懂它的工作原理。为什么Git可以管理版本?基本命令git add和git commit到底在干什么?

在这篇文章中,我将用一个例子来解释Git的运行过程,帮助你理解Git的工作原理。

初始化

让我们创建一个项目的目录,然后进入该目录。

$mkdirgit-demo-project$cdgit-demo-project

如果想管理项目的版本,那么我们应该做的第一件事情就是通过git init初始化。

$gitinit

git init只做了一件事情,那就是在项目的根目录下创建.git子目录来保存版本信息

$ls.gitbranches/configdescriptionHEADhooks/info/objects/refs/

上述命令显示了.git子目录中的内容。

保存对象

接下来让我们创建一个新的空文件test.txt。

$touchtest.txt

然后把这个文件添加到Git代码库中,这一步将创建test.txt现有内容的一个副本。

$githash-object-wtest.txte69de29bb2d1d6434b8b29ae775ad8c2e48c5391

在上述代码中,git hash-object命令将test.txt现有的内容压缩成二进制文件,并保存到Git中。该压缩文件叫做Git对象,保存在.git/objects目录中。

我们可以通过这个命令根据对象的文件名获取当前内容,并计算成SHA1 哈希(长度为40的字符串)。让我们看看下列新生成的Git对象文件。

$ls-R.git/objects.git/objects/e6:9de29bb2d1d6434b8b29ae775ad8c2e48c5391

如上述代码所示,.git/objects目录下又多出了一个子目录,而且这个子目录名是上述哈希值的前两个字符。在这个子目录下有一个文件,文件名是上述哈希值中其余的38个字符。

让我们再来看看文件内容。

$cat.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

上述代码输出的文件内容是一些二进制字符。你可能会问既然test.txt是空文件,又怎么会有这些内容呢?这是因为该二进制对象中还存储了一些元数据。

如果你想看看该文件原始的文本内容,那么应该使用git cat-file。

$gitcat-file-pe69de29bb2d1d6434b8b29ae775ad8c2e48c5391

因为原文件为空,所以上述命令什么都没有显示。现在我们往test.txt文件中写点东西。

$echo'helloworld'>test.txt

这个文件的内容已经改变了,所以你需要再次把它保存为Git对象。

$githash-object-wtest.txt3b18e512dba79e4c8300dd08aeb37f8e728b8dad

如上述代码所示,test.txt的哈希值已经随着文件内容的改变而发生了变化。同时还生成了新文件.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad。现在你可以看到这个文件的内容了。

$gitcat-file-p3b18e512dba79e4c8300dd08aeb37f8e728b8dadhelloworld

更新索引

当文件保存成二进制对象以后,你需要告诉Git哪个文件发生了变化。Git会在一个名叫“索引”(或阶段)的区域记录所有发生了变化的文件。然后等到所有的变更都结束后,将索引中的这些文件一起写入正式的版本历史记录中。

$gitupdate-index--add--cacheinfo1006443b18e512dba79e4c8300dd08aeb37f8e728b8dadtest.txt

上述命令记录了文件名test.txt、二进制对象名(哈希值)以及索引中文件的访问权限。

git ls-files命令可以显示索引中当前的内容。

$gitls-files--stage1006443b18e512dba79e4c8300dd08aeb37f8e728b8dad0test.txt

上述代码显示索引中只有一个test.txt文件,还显示了该文件的二进制对象名和访问该文件的权限。如果你知道该二进制对象名,就可以查看.git/objects子目录中该文件的内容。

git status命令可以输出更多可读的结果。

$gitstatusChangestosubmit:Thenewfile:test.txt

上述代码显示索引中只有一个新文件test.txt,该文件正在等候写入版本的历史记录中。

git add命令

针对每个文件执行上述两个步骤非常繁琐。所以Git提供了git add命令来简化这些操作。

$gitadd--all

上述命令相当于针对当前项目中所有发生了变化的文件执行上述两个步骤。

提交(Commit)

索引保存发生了变化的文件信息。等到修改完成,所有这些信息都会被写入版本的历史记录中,这相当于生成一个当前项目的快照。

项目的历史记录由不同时间点的项目快照组成。Git可以将项目恢复成任何一个快照。在Git中“快照”有一个专门的术语,即“提交”(commit)。所以生成快照也可以称之为完成提交。

下列所有“快照”的引用指的都是提交。

完成提交

首先,我们需要设置用户名和邮件地址。在你保存快照的时候,Git需要记录是谁执行的提交。

$gitconfiguser.name"username"$gitconfiguser.email"Emailaddress"

接下来,保存现有的目录结构。在本文的前面我们讨论了保存对象只会保存一个文件,并不会记录文件之间的目录结构。

git write-tree命令可以根据当前目录结构生成一个Git对象。

$gitwrite-treec3b8bb102afeca86037d5b5dd89ceeb0090eae9d

在上述代码中,目录结构保存成了二进制对象,而对象的名字是哈希值。它也保存在.git/objects目录中。

让我们来看看该文件的内容。

$gitcat-file-pc3b8bb102afeca86037d5b5dd89ceeb0090eae9d100644blob3b18e512dba79e4c8300dd08aeb37f8e728b8dadtest.txt

可以看到,当前目录中只有一个文件test.txt。

这个所谓的快照就是保存当前的目录结构,以及每个文件相对应的二进制对象。之前的操作已经保存了文件结构,所以现在你需要把这个目录结构和一些元数据一起写入版本的历史记录中。

git commit-tree可以将目录树对象写入到版本的历史记录中。

$echo"firstcommit"|gitcommit-treec3b8bb102afeca86037d5b5dd89ceeb0090eae9dc9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

在上述代码中,在提交时你需要提供提交的描述,而且你可以通过echo "first commit"提供提交描述。git commit-tree命令会根据元数据以及目录树生成一个Git对象。现在,让我们来看看该对象的内容。

$gitcat-file-pc9053865e9dff393fd2f7a92a18f9bd7f2caa7fatreec3b8bb102afeca86037d5b5dd89ceeb0090eae9dauthorjam1538889134+0800committerjam1538889134+0800firstcommit

在上述代码中,第一行输出是对应于该快照的目录树对象,而第二行和第三行是有关作者和提交者的信息,最后一行内容是提交的描述。

通过git log命令我们还可以查看某个快照的信息。

$gitlog--statc9053865e9dff393fd2f7a92a18f9bd7f2caa7facommitc9053865e9dff393fd2f7a92a18f9bd7f2caa7faAuthor:jamDate:SunOct713:12:142018+0800firstcommittest.txt|1+1filechanged,1insertion(+)

git commit命令

Git提供了git commit来简化上述提交操作。在保存到索引后,你只需要执行git commit命令,就可以同时提交目录结构和描述,并生成快照。

$gitcommit-m"firstcommit"

另外,还有两个命令也非常实用。

通过git checkout命令,我们可以切换到某个快照。

$gitcheckoutc9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

通过git show命令,我们可以显示某个快照的所有代码变更。

$gitshowc9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

分支(branch)

然而,如果你使用git log命令来查看整个版本的历史记录时,却无法看到刚刚生成的快照。

$gitlog

上述命令输出为空。这是为什么?这个快照刚刚不是写入到历史记录中了吗?

真相是:git log命令只可以显示当前分支上的变化。尽管我们已经提交了这个快照,但是还没有记录这个快照属于哪个分支。

分支是快照的指针,分支的名字就是该指针的名字。虽然哈希值不可读,但是分支允许用户给快照起别名。另外,分支还会自动更新,如果当前分支是一个新的快照,那么这个指针会自动指向它。例如,主分支(master branch)有一个名为master的指针指向主分支当前的快照。

用户可以为任何快照创建新指针。例如,如果你想创建一个新的fix-typo分支,那么只需创建一个名为fix-typo的指针,并指向一个快照。因此,在Git中创建一个新分支非常容易,而且开销非常低。

Git有一个特殊的指针HEAD,它始终指向当前分支中最新的那个快照。另外,Git还提供了快捷方式。例如,HEAD^指向HEAD之前的快照(父节点),而HEAD~6指向HEAD之前的第六个快照。

每个分支的指针都是一个文本文件,存储在.git/refs/heads/目录中。文件的内容是它指向的快照的二进制文件名(哈希值)。

更新分支

下面我们将演示如何更新分支。首先,修改test.txt。

$echo"helloworldagain">test.txt

然后保存二进制对象。

$githash-object-wtest.txtc90c5155ccd6661aed956510f5bd57828eec9ddb

接下来,将该对象写入索引,并保存目录结构。

$gitupdate-indextest.txt$gitwrite-tree1552fd52bc14497c11313aa91547255c95728f37

最后,提交目录结构,并生成一个快照。

$echo"secondcommit"|gitcommit-tree1552fd52bc14497c11313aa91547255c95728f37-pc9053865e9dff393fd2f7a92a18f9bd7f2caa7fa785f188674ef3c6ddc5b516307884e1d551f53ca

在上述代码中,我们可以通过git commit-tree命令的参数-p来指定父节点,即以哪个快照为基础。

下面我们把快照的哈希值写入到.git/refs/heads/master文件中,并让master指针指向该快照。

$echo785f188674ef3c6ddc5b516307884e1d551f53ca>.git/refs/heads/master

现在,通过git log命令你可以看到两个快照了。

$gitlogcommit785f188674ef3c6ddc5b516307884e1d551f53ca(HEAD->master)Author:jamDate:SunOct713:38:002018+0800secondcommitcommitc9053865e9dff393fd2f7a92a18f9bd7f2caa7faAuthor:jamDate:SunOct713:12:142018+0800firstcommit

git log命令的运行过程大致如下:

找到HEAD指针对应的分支。在上述示例中为master。

找到master指针指向的快照。在上述示例中为785f188674ef3c6ddc5b516307884e1d551f53ca。

找到父节点(即前一个快照)c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa。

等等,最后显示当前分支中所有的快照。

另外,上述我们曾提到分支指针是动态的,下述三个命令会自动覆盖分支指针。

Git commit:当前分支的指针将移动到新创建的快照上。

Git pull:在当前分支和远程分支合并后,指针会指向新创建的快照。

Git reset [commit_sha]:当前分支的指针将被复位到某个指定的快照上。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 二进制
    +关注

    关注

    2

    文章

    700

    浏览量

    41231
  • Git
    Git
    +关注

    关注

    0

    文章

    192

    浏览量

    15396

原文标题:20分钟教你搞懂Git!

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    教你如何学习ARM设计详细教程(共20篇)

    教你如何学习ARM设计详细教程(共20篇)ARM 汇编指令集大全 ARM指令速查手册 教你如何学习ARM设计--32 位操作 教你如何学习ARM设计--32 位规则
    发表于 12-30 15:22

    40分钟教你学会什么是ARM架构

    门老大Chris Shore 做了一个最短小精悍的视频,用40分钟教会大家到底什么是ARM架构,并且ARM公司的Video Team团队帮忙制作了中文字幕,方便大家学习观看。请大家看这里:
    发表于 10-14 16:07

    电脑用到不到20分钟后就黑屏

    各位大神我的电脑用不到20分钟就黑屏,后在开机又能用个20分钟这样就又黑屏了,华硕的
    发表于 07-19 09:03

    3分钟教你使用STM32CubeMX配置工程并移植机智云生成的协议

    3分钟教你使用STM32CubeMX配置工程并移植机智云生成的协议
    发表于 09-29 15:13

    10分钟学会FPGA设计

    10分钟学会FPGA设计
    发表于 09-27 10:57

    AD17 每隔20分钟弹出Error对话框

    `Altium designer V17.1.6 弹出Error对话框,如下图。用鼠标点击“OK”键后,对话框消失,但20分钟后又弹出这个Error对话框。不胜其烦。是何道理?`
    发表于 10-26 11:37

    请问51定时器跑11分钟就有20多秒的误差正常吗?

    如题,我用51开发板,芯片用的是STC89C52RC,定时器产生软时钟,跑11分钟就有20多秒的误差,这个正常吗?
    发表于 03-20 05:38

    教你一招分分钟实现频谱仪带宽的正确设置

    教你一招分分钟实现频谱仪带宽的正确设置
    发表于 05-07 06:36

    分钟搞懂PID控制算法

    【Arduino 101】五分钟搞懂PID控制算法物料清单尺寸接线文章目录物料清单尺寸接线物料清单Arduino Uno x 1超声波模块(HC-SR04)x 1舵机(Tower Pro
    发表于 06-28 07:53

    CH563运行WEB-SERVER 20分钟后发热严重怎么改善?

    CH563运行WEB-SERVER 20分钟后发热挺严重的,估计能有50度以上。PCB是敞开的,环境温度26度,RSETE连接12.4K电阻,哪位运行过WEB SERVER例程的,芯片有没有发热的现象?明天吧RSETE电阻换成15K再观察
    发表于 06-06 07:35

    Git是什么?Git的基本使用资料说明

      Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一)。
    发表于 05-29 17:56 1次下载
    <b class='flag-5'>Git</b>是什么?<b class='flag-5'>Git</b>的基本使用资料说明

    为什么说Git把SVN拍在沙滩上了呢?

    有不同的体验。 一、Git是分布式的,SVN是集中式的 这是 Git 和 SVN 最大的区别。若能掌握这个概念,两者区别基本搞懂大半。因为 Git 是分布式的,所以
    的头像 发表于 04-30 11:57 1253次阅读
    为什么说<b class='flag-5'>Git</b>把SVN拍在沙滩上了呢?

    【硬核科普】3分钟带你搞懂PCB压合工艺

    孔铜免费检测:登录华秋电路官网>进入用户中心>点击孔铜检测>一键申请。点击孔铜检测0元PCB打样原文标题:【硬核科普】3分钟带你搞懂PCB压合工艺文章出处:【微信公
    的头像 发表于 08-12 09:31 749次阅读
    【硬核科普】3<b class='flag-5'>分钟</b>带你<b class='flag-5'>搞懂</b>PCB压合工艺

    git rebase和git merge的区别

      解决冲突 git rebase和git merge的区别 分支合并 git merge是用来合并两个分支的。 比如:将 b 分支合并到当前分支。 同样git rebase b,也是
    的头像 发表于 07-05 09:54 359次阅读
    <b class='flag-5'>git</b> rebase和<b class='flag-5'>git</b> merge的区别

    一文搞懂版本控制与Git

    在这个码代码的时代,我们越来越离不开版本控制工具。而在众多版本控制工具中,Git无疑是最为强大和流行的。
    的头像 发表于 10-20 09:46 193次阅读
    一文<b class='flag-5'>搞懂</b>版本控制与<b class='flag-5'>Git</b>