1 minute read

为什么要学git

最近QQ同学正在基于omnet开发自己的工程,让她困惑的是:如何记住自己的每次修改?特别是在大型程序开发中,这并不是一件容易的事情。不过我们可以通过git来辅助管理代码改动,更妙的是,我们还能将其上传到代码托管网站,如githubgitee上,实现多人同时开发。本文将分别从git的基本概念,git的使用,将git上传到github三个方面阐述git的用法。

git的基本概念

什么是git呢?不严谨的来说,git实际上是对每次提交做一次快照(snapshot),并且管理这一系列快照的工具。

alt text 如上图所示,github由三个区组成,分别是工作区、暂存区以及 Git 目录。并且这三个部分可以通过箭头的形式进行转换。

  • 工作区:顾名思义,是工作的区域,我们对代码所有的修改在这个区进行,此时文件的状态为已修改(modified),使用git add 可以将结果存入暂存区。
  • 暂存区:使用git add后,对此时的工作区做快照,存在暂存区,此时文件状态为已暂存(staged)。用户可以在工作区继续修改,通过git add多次更新快照。结束修改后,通过git commit 添加一些对此次修改的描述,并进行提交。
  • Git 目录:当提交完修改后,这笔提交就正式存入了Git 目录中。可以使用git log查看每笔提交的具体内容。我们向云端的代码仓上传和下载的也是这个部分的内容。

git的基本使用

在本地配置一个github仓库

  1. 使用git -v 查看你本地是否有git。如果没有,请根据你的平台,对应下载git工具。
  2. 在合适的位置新建一个文件夹,使用git init来初始化git仓库。

修改文件,并提交到暂存区

  • 新建一个文件,这就是我们需要提交的文件
  • 使用git status来查看工作区此时的情况 alt text 可以看到,这里出现了两条信息:
  1. Changes not staged for commit:这说明git管理的文件中出现了修改。
  2. Untracked files: 说明用户新建了文件,并且此文件尚未被git跟踪,需要手动使用git add <filename>通知git对其进行管理。

当然,我们还可以通过git add加上一些选项,全部或部分的对修改进行管理。

以下是这个阶段常用的一些命令:

命令 含义
git status 查看此时工作区的状态
git diff 查看此时工作区尚未保存到暂存区的,所有已被追踪的文件的具体变化
git restore 丢弃某些修改
git add <file> 提交单个文件变化
git add -A 提交所有变化
git add -u 提交被修改(modified)和被删除(deleted)的文件, 不包括新文件(new
git add . 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
git add -h git add 查看帮助,git add –help可以查看更详细内容

tips: 在每次提交前使用git status查看工作区状态是一个好习惯,它能确保我们每次提交不会遗漏修改!

添加commit信息,存入git目录

前面已经说到,可以使用git commit写入评论信息。此处可能需要使用到vimvim是一款常用于linuxmacos下的文件编辑器,如果你对它的操作不熟悉,请自行谷歌学习。 alt text 按照提示输入信息后退出,使用git log,我们就可以看到刚刚的提交了。 alt text
当你想多次提交到同一个commit中,请使用git commit –amend。

git 进阶之路

学完了上述内容,相信你还有很多疑问。比如说,我已经将某次修改提交到了git目录或是暂存区,但此时发现修改不对,难道要再重新手动把它改回来吗?是否有更便捷的方法呢?或是我想基于一份代码做多种修改,难道需要本地创建多个git仓库?这些问题在开发中每天都会遇到,接下来让我们一一解决它们。

指针的妙用

让我们回到git log显示的信息。这次让我们关注一些细节。 alt text
可以看到commit后面跟了一串数字,我们把它叫做commit id,这是通过哈希算法得出的哈希值,在这里,我们只要知道这个值是唯一的,也就是说,每笔提交都拥有独一无二的commit id。

为了满足基于一份代码做多种修改的需求,git提出了branch的概念。何为branch,实际上是一个可以移动的指针。使用git branch testing,新建一个名为testing的新分支。再次使用git log查看git目录,可以看到多了一个testing的分支。 alt text
此时的git目录如图所示:
alt text
98ca9,34ac2,f30ab指代三次commitcommit id,提交顺序为98ca9 -> 34ac2 -> f30ab

注意:HEAD是一个特殊的指针,它永远指向当前branch的最新一笔提交。

接下来使用git checkout testing切换到已经存在的分支, 可以看到HEAD指针此时指向了testing分支。

alt text

此时git目录就变为了:

alt text

我们再进行一次提交,会看到此时的testing指针向前移动,指向了最新一次提交的commit id。而master的指针却不会移动。 alt text
让我们使用git checkout master 切换回master分支,可以看到HEAD指向了master。并且git log中,最新的commit不见了。 alt text
由此可以知道,利用branch的特性,我们可以在任意commit处创建新的branch,并且不同的branch之间互不影响。

alt text

在不同的commit之间切换

假设QQ已经进行了三次提交,commit ida - b - c,此时QQ同学突然发现自己需要退回到a时候的状态,她要怎么做呢?前面我们讲到,git使用HEAD指针来指示此分支的最后一笔提交,那我们可以将HEAD和分支的指针都指向某一个commit id处。而git reset 就是这样的命令。
针对刚刚的场景,QQ同学可以采用 git reset --hard a,让指针重新指向commit id为 a 处,也可以使用git reset --hard HEAD~2。来让HEAD的指针回退2个提交。 此外,git reset不仅可以用来回退,只要你知道commit idHEAD指针也可以重新指向commit c的位置。
如果你很不幸的忘记了自己是如何移动HEAD指针的,也没有关系。使用git reflog可以查看你的每次操作。 alt text 第一部分是HEAD每次操作指向的commit id,这里使用的较短的哈希值,和git log中的长哈希值是对应的,也等效于HEAD@{i},也就是说使用git reset --hard 99678a8git reset --hard HEAD@{4}是等效的。

第二部分可以看到,git reflog还显示了当时指向commit id的对应指针。

要注意,git reset的本质是移动指针,请你思考一下,在这种情况下,使用git reset --hard 87ab2,git目录是怎样变化的呢? alt text

工作区、暂存区、 Git 目录的相互切换

  • Git 目录回到暂存区
    前面我们讲到如何使用git reset --hard,而其实还有一个非常相似的命令git reset --soft。它的区别是,此时会将这条commit的内容回退到暂存区,我们可以重新使用git commit来将它提交到git目录。

  • 暂存区回到工作区
    使用git reset [file]回退单个文件或是git reset回退所有文件。

alt text

TBC

  • 使用github管理你的代码仓库

Leave a comment