当前位置: 首页 > 编程日记 > 正文

20分钟教你搞懂Git!

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

640?wx_fmt=png

以下为译文:

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

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

640?wx_fmt=png


初始化


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

$ mkdir git-demo-project
$ cd git-demo-project

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

$ git init

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

$ ls .git

branches/
config
description
HEAD
hooks/
info/
objects/
refs/

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


保存对象


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

$ touch test.txt

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

$ git hash-object -w test.txt

e69de29bb2d1d6434b8b29ae775ad8c2e48c5391

在上述代码中,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。

$ git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391

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

$ echo 'hello world' > test.txt

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

$ git hash-object -w test.txt

3b18e512dba79e4c8300dd08aeb37f8e728b8dad

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

$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad

hello world


更新索引


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

$ git update-index --add --cacheinfo 100644 \
3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt

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

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

$ git ls-files --stage

100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0   test.txt

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

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

$ git status

Changes to submit:
    The new file:   test.txt

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


git add命令


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

$ git add --all

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


提交(Commit)


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

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

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


完成提交


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

$ git config user.name "username" 
$ git config user.email "Email address"

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

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

$ git write-tree

c3b8bb102afeca86037d5b5dd89ceeb0090eae9d

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

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

$ git cat-file -p c3b8bb102afeca86037d5b5dd89ceeb0090eae9d

100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    test.txt

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

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

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

$ echo "first commit" | git commit-tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d

c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

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

$ git cat-file -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
author jam  1538889134 +0800
committer jam  1538889134 +0800

first commit

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

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

$ git log --stat c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

commit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: jam 
Date:   Sun Oct 7 13:12:14 2018 +0800

    first commit

 test.txt | 1 +
 1 file changed1 insertion(+)


git commit命令


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

$ git commit -m "first commit"

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

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

$ git checkout c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

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

$ git show c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa


分支(branch)


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

$ git log

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

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

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

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

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

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


更新分支


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

$ echo "hello world again" > test.txt

然后保存二进制对象。

$ git hash-object -w test.txt

c90c5155ccd6661aed956510f5bd57828eec9ddb

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

$ git update-index test.txt
$ git write-tree

1552fd52bc14497c11313aa91547255c95728f37

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

$ echo "second commit" | git commit-tree 1552fd52bc14497c11313aa91547255c95728f37 -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa

785f188674ef3c6ddc5b516307884e1d551f53ca

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

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

$ echo 785f188674ef3c6ddc5b516307884e1d551f53ca > .git/refs/heads/master

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

$ git log

commit 785f188674ef3c6ddc5b516307884e1d551f53ca (HEAD -> master)
Author: jam 
Date:   Sun Oct 7 13:38:00 2018 +0800

    second commit

commit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: jam 
Date:   Sun Oct 7 13:12:14 2018 +0800

    first commit

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

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

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

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

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

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

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

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

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

原文:

https://www.tutorialdocs.com/article/how-git-works.html

作者:Alex

译者:弯月,责编:郭芮



公开课预告

文本分类

在文本分类领域中的模型和算法有很多,那如何为你的文本分类问题选择合适的模型呢?本节公开课通过对比来阐述不同的算法、模型在实际的应用过程中的区别,以及在文本分类实践中所遇到的各种坑。


640?wx_fmt=jpeg

推荐阅读

  • 最懂区块链的十大女神,值得你关注 | 年度盘点

  • “腾讯也感受到危机了!”

  • 程序员依然是这个时代,贫寒学子翻身的不二选择

  • 讲述:一个月薪12000的北京程序员的真实生活

  • 程序员为啥365天都背电脑包?这答案我服!


点击“阅读原文”,打开APP 阅读更顺畅 

相关文章:

android 长按赋值功能,android实现WebView中长按选中复制文本操作

啥都不说了,老司机直接移步GITHUB看源码吧:https://github.com/deaboway/AndroidWebViewTextSelect万一不work,一定不是代码的问题,你可以自查链接中的如下情况CSS控制页面文字不能被选中user-select:none;body{-moz-user-select:…

如何找回丢失的Vista系统“休眠”菜单

如何让Vista系统“休眠”菜单重见天日一些使用Windows Vista的朋友为了节省磁盘空间,在命令提示符下使用命令关闭休眠功能。但是如果再用相同的方法打开休眠功能时,就会发现,即使恢复了功能,“休眠”菜单还是看不见,这…

go3--常量和类型转换

/* Go中不存在隐式转换&#xff0c;所有类型转换必须显式声明 转换只能发生在两种相互兼容的类型之间 类型转换的格式&#xff1a;<ValueA> [:] <TypeOfValueA>(<ValueB>)全局变量可以使用var&#xff08;&#xff09;的形式&#xff0c;局部变量不可以使用v…

android倒计时实现方法,Android实现倒计时方法汇总

Android开发中经常会有倒计时的功能&#xff0c;下面将总结出常见的集中实现方式。1.直接使用Handler的消息机制来实现xml布局中文件如下&#xff1a;android:layout_width"match_parent"android:layout_height"match_parent"android:orientation"hor…

今晚8点直播 | 详讲NLP的经典应用实践——文本分类

文本分类问题是企业在 NLP 领域中处理文本数据时经常会遇到的一个问题&#xff0c;很多时候&#xff0c;我们需要将文本信息进行分类&#xff0c;或提相关的接口以供外部进行文本上传&#xff0c;在针对于用户所上传的文档信息就需要进行文档内容的分类&#xff0c;那么针对于这…

谈论 嵌入式系统

引用 嵌入式系统嵌入式系统http://www.lumit.org/index.htm嵌入式相关的网站http://www.mcu123.com/news/Article/web/uc/200611/3939.html转载于:https://www.cnblogs.com/stoneresearch/archive/2008/10/21/4336381.html

SharePoint Server 2013 之四:部署SharePoint企业版

在上篇文章我们完成了SharePointServer 2013 必备的组件&#xff0c;用户可根据自己需求联网安装或离线安装。接下来我们进入SharePoint 企业版的部署。 运行SharePointServer 2013 SP1 安装程序&#xff0c;点击“安装SharePoint Server”如下图&#xff1a; 企业版安装是需要…

android 监测内存泄漏工具,LeakCanary:Android内存泄漏检测工具

LeakCanaryA memory leak detection library for Android and Java.“A small leak will sink a great ship.” - Benjamin FranklinGetting startedIn your build.gradle:dependencies {debugImplementation com.squareup.leakcanary:leakcanary-android:1.6.1releaseImplemen…

为什么说可视化编程是糟糕的想法?

可视化编程语言可以让程序员通过操纵图形元素来创建程序&#xff0c;而无需键入文本命令。众所周知的例子是 Scratch&#xff0c;这是一种麻省理工学院开发的可视化编程语言&#xff0c;用来教孩子们学编程。该语言的优势在于新手和普通用户可以更容易接触编程。二十世纪九十年…

7年增长16倍,清华AI+ML课程学生数暴增 | AI Index 2018

整理 | 非主流出品 | AI科技大本营用数据解读 AI。昨日&#xff0c;来自斯坦福大学、MIT、哈佛、OpenAI 等高校与企业的多位专家正式发布了 2018 年度 AI Index 报告&#xff0c;用一系列数据全面回顾了过去几年里 AI 领域的全球发展。营长挑了一些重点内容&#xff0c;为大家解…

RunTime的使用-Category改变整个项目全部字体

在项目比较成熟的基础上&#xff0c;遇到了这样一个需求&#xff0c;应用中需要引入新的字体&#xff0c;需要更换所有Label的默认字体&#xff0c;但是同时&#xff0c;对于一些特殊设置了字体的label又不需要更换。乍看起来&#xff0c;这个问题确实十分棘手&#xff0c;首先…

android 耳机红外线,红外线耳机制作方法

本文介绍的语音红外转发器具有结构简单、易于制作、无干扰、低噪声的特点。工作原理&#xff1a;转发器由发射和接收两部分组成。见附图1。鉴频后的伴音(音频)信号经三极管V放大后推动红外发射管。由于发射管的发光强度与通过的电流成正比&#xff0c;所以D1、D2所发出的红外光…

解决load cycle count的一个偏方,告别硬盘卡卡响

load cycle count猛增&#xff0c;笔记本电脑硬盘喀嚓喀嚓响&#xff0c;我倒不担心硬盘寿命&#xff0c;但是实在烦人那声音&#xff0c;系统也时常被卡一下。我曾使用了hdparm -B 254 /dev/sda 的方法&#xff0c;但是硬盘升温太明显&#xff0c;右掌托烫得忍无可忍。苦寻方法…

AI工程的实践者:普元积极将场景落地,为企业提供智能化解决方案

作者 | Jane出品 | AI科技大本营11 月 8-9 日&#xff0c;CSDN 和 AICamp 联合举办的 AI 开发者大会在北京顺利举行。普元移动产品线总经理郝振明发表了《基于机器学习的工程实践》的主题演讲&#xff0c;并接受了 AI科技大本营的专访。以下内容为郝振明的演讲与采访总结&#…

android用户界面设计:基本按钮,Android用戶界面設計:基本按鈕

本文向你展示了在你的android應用程序中創建一個簡單的Button或ImageButton控件的步驟。首先&#xff0c;你會學到如何向你的布局文件中添加按鈕控件。然後你會學習如何用兩種方法處理用戶對按鈕的點擊。最後&#xff0c;我們討論android中按鈕控件一些其它的可用特性。第1步&a…

快速浏览Silverlight3 Beta:当HLSL遇上Silverlight

HLSL高级着色器语言&#xff08;High Level Shader Language&#xff0c;简称HLSL&#xff09;&#xff0c;由微软拥 有及开发的一种语言&#xff0c;只能供微软的Direct3D使用。 HLSL是微软抗衡GLSL的产品&#xff0c;同时不能与OpenGL标准兼容。他跟Nvidia的Cg非常相似。 看…

“80后”财富新贵创业秘诀

"80后"财富新贵创业秘诀:具有冒险和创新精神 不论是文化市场&#xff0c;还是经济市场&#xff0c;当许多人还认为还是“60后”或“70后”的天下时&#xff0c;“80后”财富新贵已在不知不觉中浮出水面&#xff0c;并试图用自己的实力证明新一代的崛起。李想、戴志康…

小插件 打开Android程序动画,android-单击小部件后如何启动活动?

这就是对我有用的…onUpdate方法代码应为&#xff1a;Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {for (int i 0; i < appWidgetIds.length; i) {int appWidgetId appWidgetIds[i];try {Intent intent new …

“深度学习之父”大谈AI:寒冬不会出现,论文评审机制有损创新

整理 | 琥珀出品 | AI科技大本营【AI 科技大本营导读】近日《连线》杂志发表了一篇文章&#xff0c;记录了与“深度学习之父” Geoffrey Hinton 围绕人工智能伦理、技术、学术等领域的采访实录。当被问到如今人工智能是否将走进寒冬时&#xff0c;Hinton 的回答非常坚决&#x…

金山词霸2009牛津版

http://download.iciba.com/Pw2009_oxf/Powerword2009Oxf.25269.4011.exe新版本的词霸2009牛津版的 需要的朋友下载看看 转载于:https://blog.51cto.com/zmdzhangzhe/112418

面向对象之数值的悲剧(8月28日会议有感)

枚举的悲剧 枚举基本用法大家应该都很熟悉&#xff0c;在我们去避免硬编码&#xff0c;增强代码可读性&#xff0c;可维护性方面很好用。不过话说枚举底层还是比较复杂的&#xff0c;以前看过一些关于枚举的说明。至少C#里边的枚举是很复杂的&#xff0c;本身是结构类型&#x…

C++虚函数探索!

C中的虚函数实现了C中的多态。昨天C老师着重讲了讲虚函数。这个很重要&#xff0c;也有点玄机在里面。 下面阐述一下理论&#xff1a; C的类机制中有支持多态的技术来解决抽象编程。使用的是滞后捆绑技术。即预先设定其成员函数虚函数性质&#xff0c;使得任何捆绑该成员函数的…

htc820+android+l,首款高通64位八核 HTC Desire 820评测

9月初的IFA2014展会期间&#xff0c;多款搭载64位处理器的新品智能手机扎堆发布&#xff0c;也算是拉开了64位处理器安卓手机的时代序幕。其中&#xff0c;最引人注目的新品之一莫过于HTC Desire 820&#xff0c;它于北京时间9月4日在德国柏林发布&#xff0c;拔得了全球首款64…

关于正则表达式 g,m 参数的总结,为了回答“正则表达式(/[^0-9]/g,'')中的/g是什么意思?”...

为了解答“正则表达式(/[^0-9]/g,)中的"/g"是什么意思&#xff1f;”这个问题&#xff0c;也为了能够便于大家对正则表达式有一个更为综合和深刻的认识&#xff0c;我将一些关键点和容易犯糊涂的地方再系统总结一下。 总结1&#xff1a;附件参数g的用法 表达式加上参…

那位13岁就当上老板的开发者是如何炼成的?

当我们听到有关年轻有为的企业家的故事时&#xff0c;大多会想到 25 到 30 岁左右的年轻人。毕竟&#xff0c;Google、亚马逊、Facebook、Twitter、LinkedIn、Pinterest、Instagram、Snapchat 以及其它很多公司的创始人都是在他们 20 多岁时创办的这些企业。随着人们与科技的联…

phonegap android,Phonegap 3不适用于Android Studio

对我来说,这似乎很简单,但我根本做不到.我已经成功安装了npm install -g phonegap并安装了phonegap.C:\var\www\sexdiaries.co.uk>phonegap create sexdiaries -n SexDiaries -i co.uk.sexdiaries.app然后,我被告知Here尝试运行andriod但出现以下错误C:\var\www\sexdiaries.…

安装VCenter提示数据库排序规则有问题

安装VCenter提示数据库排序规则有问题 有时候在安装sql server 数据库时你如果修改了排序规则&#xff0c;那么在安装VCenter时它会提示你的数据库排序规则有问题&#xff0c;不让你安装。这个时候你去修改一下数据库规则就可以继续安装了。 解决方法&#xff1a; 1.把安装光盘…

点滴印象中的周其凤校长

原文&#xff1a;[url]http://blog.sina.com.cn/s/blog_4908ded80100bbui.html?tj1[/url]2003年9月&#xff0c;我进入吉林大学读书&#xff0c;第二年周其凤成为吉林大学新任校长。此后的三年&#xff0c;我见过校长两次&#xff0c;这两次&#xff0c;校长的风格给我留下了深…

开源50万行代码,百亿广告分成,百度智能小程序能成吗?

作者 | 非主流出品 | AI科技大本营终于&#xff0c;BAT 在小程序的赛道上展开了激战&#xff0c;而这一场战争得到了百度前所未有的重视。9 月 4 日&#xff0c;百度总裁张亚勤称拉动百度业务的“新四小龙”——智能小程序、信息流、短视频/小视频以及百度云。紧接着&#xff0…

接近WinHEC 2008

第一次听说windows硬件工程大会还以为微软要讲她出的硬件的一个技术交流大会&#xff0c;后来才了解到是微软公司面向个人电脑终端、服务器、硬件设备以及驱动程序的最具前瞻性的全球硬件技术信息盛会。而不是讲硬件本身&#xff0c;是与硬件相关的软件产品。今年是第17届WinHE…