Git 的原理与使用(上)

Git是一个分布式版本控制系统,它被广泛用于协作开发和管理软件项目。开发人员可以通过Git来跟踪文件的变化、协调工作、并管理项目的不同版本。

Git允许用户在不同的分支上开发新功能,然后合并这些分支并确保团队成员之间的工作协调一致。此外,Git还提供了强大的工具,如提交、合并、回滚等等。因此通过 Git,团队能够高效地管理项目并追踪代码的变化历史。

本文整理自博主日常编码实践中对Git的使用,包括Git的相关概念,基本操作等,希望能带给各位小伙伴们一个关于Git的清晰认识,快速上手。

目录

一、认识 Git

1.提出问题

2.如何解决:版本控制器

二、Git 安装

Linux-centos

Linux-ubuntu

Windows

三、Git 的初始化与配置

1.创建 Git 本地仓库

2.配置 Git

3.查看配置

4.删除配置

四、认识工作区、暂存区、版本库

1.添加文件--场景一

2.查看.git文件

3.添加文件--场景二

4.修改文件

5-版本回退 reset

6-撤销修改

情况一:对于工作区的代码,还没有add

情况二:已经add,但没有commit

情况三:已经add,并且也commit了

7-删除本地仓库中的文件

**小结


一、认识 Git

1.提出问题

不知道你在工作或学习时有没有遇到这样的情况:我们在编写各种文档时,为了防止文档丢失或更改失误,又或是希望在失误后能恢复到原来的版本,不得不复制一个原文档的副本,比如:

“报告-v1”

“报告-v2”

“报告-v3”

“报告-确定版”

“报告-最终版”

“报告-绝对是最终版本再改是狗”

...

每个版本内容各不相同,但最终往往会只有一份报告将为我们所用。而由于每份报告是迭代产出的,于是每次复制粘贴副本,产出的文件就越来越多。

文件多不是问题,问题是:随着版本数量的不断增多,你还能记得这些版本各自都做了哪些修改吗?

文档如此,我们写的项目代码时也是存在这个问题的。

2.如何解决:版本控制器

为了能够让我们更方便地管理不同版本的文件,便有了版本控制器

所谓版本控制器,可以简单地理解为“一个能让你了解到某个文件的历史版本以及发展过程的系统”。换句话说,版本控制器就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也支持多人协同作业。

目前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的文件,例如doc、excel、dwg、dgn、rvt等等。而对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件。

有一点需要明确:所有的版本控制系统(Git也不例外)只能跟踪文本文件的改动,比如 txt 文件,网页,所有的程序代码等等。对于文本文件,它可以告诉你每次文件内容的改动情况,比如某文件在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。

但图片、视频这类的二进制文件,虽然也能由版本控制系统管理,但是没法跟踪文件具体的变化信息的。版本控制系统只能把二进制文件的每次改动的结果串起来,只能知道某图片从100KB改成了120KB,但到底改了什么部分,它是并不知道、也没法知道的。


二、Git 安装

Git是开放源代码的代码托管工具,最早是在Linux下开发的,开始也只能应用于Linux平台,后面才慢慢地被移植到Windows下,现在,Git可以在Linux、Unix、Mac和 Windows这几大平台上正常运行了。

对于Git的安装,本文对Linux下的安装作简单介绍,其余系统不作过多说明,有需要的朋友可以自行搜索“Git安装教程”,选择与自身平台相适应的教程进行学习。

Linux-centos

以我的centos7.6为例,安装Git:

sudo yum install git -y

查看Git安装的版本:

git --version

Linux-ubuntu

以ubuntu20.04为例:

sudo apt-get install git -y

查看git安装的版本:

git --version

Windows

Windows下的安装可以看这个视频:

Windows下安装 git 和图形化界面工具

这份视频教程相对细致,且视频中还介绍了Git的UI程序小乌龟(TortoiseGit),UI界面操作Git对于初学者而言更加简洁方便,大家也可以看着下载。


三、Git 的初始化与配置

1.创建 Git 本地仓库

仓库是进行版本控制的文件目录。我们要想对文件进行版本控制,就必须先创建一个仓库出来。只有仓库下的文件才能被Git追踪管理。

创建一个Git本地仓库对应的命令为:

 git init

注意命令要在文件目录下执行,如:

[wyd@VM-4-13-centos ~]$ mkdir gitcode
[wyd@VM-4-13-centos ~]$ cd gitcode[wyd@VM-4-13-centos gitcode]$ git init
Initialized empty Git repository in /home/wyd/gitcode/.git/
[wyd@VM-4-13-centos gitcode]$ ls -al
total 12
drwxrwxr-x  3 wyd wyd 4096 Dec  1 19:55 .
drwx------ 10 wyd wyd 4096 Dec  1 19:55 ..
drwxrwxr-x  7 wyd wyd 4096 Dec  1 19:55 .git

执行git init后我们发现,当前目录下多了一个.git的隐藏文件。

.git目录是Git用来跟踪管理仓库的。注意,千万不要手动修改这个目录里面的文件,否则改坏了,Git仓库也就随之被破坏了。

.git文件中包含了Git仓库的诸多细节:

[wyd@VM-4-13-centos gitcode]$ tree .git
.git
|-- branches
|-- config
|-- description
|-- HEAD
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- prepare-commit-msg.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   `-- update.sample
|-- info
|   `-- exclude
|-- objects
|   |-- info
|   `-- pack
`-- refs|-- heads`-- tags9 directories, 13 files

这些字段代表什么含义,我们将在后续对Git的深入学习中逐步接触。 

2.配置 Git

安装Git后首先要做的事情是配置你的用户名(user.name)和email地址(user.email),这是非常重要的一步。

配置命令为:

git config

注意,执行命令时必须要在仓库里(cd gitcode):

git config [--global] user.name "YourName"
git config [--global] user.email "email@example.com"# 把YourName改成你的昵称
# 把email@example.com改成邮箱的格式,只要格式正确即可。

如:

[wyd@VM-4-13-centos linux_gitcode]$ git config user.name "zhangsan"
[wyd@VM-4-13-centos linux_gitcode]$ git config user.email "123456@qq.com"

其中,--global是一个可选项,如果使用了该选项,则表示这台机器上所有的Git仓库都会使用这个配置。

如果你希望在不同仓库中使用不同的name或e-mail,可以不加 --global 选项。 

3.查看配置

查看配置的命令为:

git config -l

git config -l命令用来列出Git的配置信息。运行该命令将显示当前仓库的Git配置项,包括用户信息、颜色设置、别名、远程仓库等等。通过git config -l可以查看当前Git仓库的所有配置项,帮助用户了解当前Git环境的设置和配置。

此外,用户还可以通过git config --global -l查看全局的Git配置项,该命令将列出全局的Git配置信息。

4.删除配置

删除配置的命令为:

git config [--global]  --unset user.name
git config [--global]  --unset user.email

如果 git conifg 的时候加了--global选项,那么删除的时候也要加上,否则是无法直接删掉 global 的配置的。


四、认识工作区、暂存区、版本库

如果直接将某个文件拷贝到 .git 文件的同级目录gitcode下,此时这个文件是不会被Git管理的。

事实上,.git 目录才是真正的Git版本库(即代码仓库)。

那么,是不是直接把文件拷贝到 .git 目录内就可以了呢?

答案是不行的,而且是万万不能这么做的!不允许在 .git 下手动进行任何修改,否则很可能导致整个本地仓库报废。我们自定义的文件,只能写在 gitcode 这个目录下。

而gitcode文件夹就是Git的工作区

(.git 文件虽然也被包括在 gitcode 文件夹中,但它并不属于工作区,而是版本库。)

  • 工作区:是在电脑上你要写代码或文件的目录。

  • 暂存区:英文叫stage或index。一般存放在目录下的index文件(.git/index)中,我们把暂存区有时也叫作索引(index)。

  • 版本库:又名仓库,英文名repository 。工作区有一个隐藏目录.git,它不算工作区,而是Git的版本库。这个版本库里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

  • 本地仓库:local repogit commit 命令就是把暂存区内的修改提交到本地仓库中。

下面这个图展示了工作区、暂存区、版本库之间的关系:

  • 图中左侧为工作区,右侧为版本库。Git的版本库里存了很多东西,其中最重要的就是暂存区(stage)。

  • 在创建Git版本库时,Git会为我们自动创建一个唯一的master分支(),以及指向master的一个指针叫HEAD。(分支和HEAD的概念后面再说)

  • 当对工作区修改(或新增)的文件执行git add命令时,暂存区目录树的文件索引会被更新。

  • 当执行提交操作 git commit 时,master分支会做相应的更新,可以简单理解为暂存区的目录树才会被真正写到版本库中。【master是本地仓库中的主要分支,可以理解为提交到master中,才是提交x真正到了本地仓库。】

由上述描述我们便能得知:通过新建或粘贴进目录的文件,并不能称之为向仓库中新增文件,而只是在工作区新增了文件。必须要通过使用git add和 git commit命令才能将文件添加到仓库中进行管理。

1.添加文件--场景一

在包含.git的目录下新建一个ReadMe文件,我们可以git add命令将文件添加到暂存区

  • 添加一个或多个文件到暂存区:git add [file1] [file2] ...

  • 添加指定目录到暂存区,包括子目录:git add [dir]

  • 添加当前目录下的所有文件改动到暂存区:git add .

使用git commit命令将暂存区内容添加到本地仓库中:

  • 提交暂存区全部内容到本地仓库中:git commit -m "message"

  • 提交暂存区的指定文件到仓库区:git commit [file1] [file2] ... -m "message"

注意,git commit后面的-m选项要跟上描述本次提交的message,由用户自己填写。这部分内容不仅绝不能省略,而且还要好好描述,message是用来记录你的提交细节的,是给其他人看的。

例如:

[wyd@VM-4-13-centos linux_gitcode]$ touch ReadMe# 在ReadMe文件中写入 hello world
[wyd@VM-4-13-centos linux_gitcode]$ echo hello world > ReadMe    
[wyd@VM-4-13-centos linux_gitcode]$ cat ReadMe
hello world# 将ReadMe的修改加入暂存区
[wyd@VM-4-13-centos linux_gitcode]$ git add ReadMe# 将暂存区的内容提交到仓库
[wyd@VM-4-13-centos linux_gitcode]$ git commit -m '提交第一个文件'
[master (root-commit) 1853b26] 提交第一个文件1 file changed, 1 insertion(+)create mode 100644 ReadMe

git commit命令执行成功后会告诉我们:1个文件被改动(也就是我们新添加的ReadMe文件),插入了1行内容(ReadMe有1行内容)。

我们还可以多次add不同的文件,而只commit一次便可以提交所有文件,是因为需要提交的文件是通通被add到暂存区中,然后一次性commit暂存区的所有修改。如:

[wyd@VM-4-13-centos linux_gitcode]$ touch file1 file2 file3
[wyd@VM-4-13-centos linux_gitcode]$ git add file1 file2 file3
[wyd@VM-4-13-centos linux_gitcode]$ git commit -m '一次性提交3个文件'
[master 68df79a] 一次性提交3个文件3 files changed, 0 insertions(+), 0 deletions(-)create mode 100644 file1create mode 100644 file2create mode 100644 file3

截至目前,我们已经更够将代码直接提交至本地仓库了。

git log命令可以帮助我们查看历史提交记录: 

[wyd@VM-4-13-centos linux_gitcode]$ git log
commit 68df79a6f2a582fd8f390eaa947577b898bc2069
Author: wyd <1256970054@qq.com>
Date:   Sun Dec 3 21:41:13 2023 +0800一次性提交3个文件commit 1853b26b95891348de92982b34f3bdbdfa01e049
Author: wyd <1256970054@qq.com>
Date:   Sun Dec 3 21:39:19 2023 +0800提交第一个文件

该命令显示从最近到最远的提交日志,并且可以看到我们commit时的日志消息。

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=onelne参数:

git log --pretty=onelne

我们看到的一大串数字是每次提交的 commit id(版本号),Git 的 commit id 不是1,2,3……递增的数字,而是一个 SHA1 计算出来的一个非常大的数字,用十六进制表示。

2.查看.git文件

先来查看.git目录的结构:

[wyd@VM-4-13-centos linux_gitcode]$ tree .git
.git
|-- branches
|-- COMMIT_EDITMSG
|-- config
|-- description
|-- HEAD
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- prepare-commit-msg.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- 18
|   |   `-- 53b26b95891348de92982b34f3bdbdfa01e049
|   |-- 25
|   |   `-- 1f5c5b7c0b8937ee454e3c1ec6a26e92951bd5
|   |-- 3b
|   |   `-- 18e512dba79e4c8300dd08aeb37f8e728b8dad
|   |-- 68
|   |   `-- df79a6f2a582fd8f390eaa947577b898bc2069
|   |-- 82
|   |   `-- a432cf4469d279b2ec65a226fbbb5c19fb56c9
|   |-- e6
|   |   `-- 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
|   |-- info
|   `-- pack
`-- refs|-- heads|   `-- master`-- tags18 directories, 24 files

其中:

1、index就是暂存区,add后的内容都是添加到这里的。

2、HEAD就是我们的默认指向master分支的指针。

[wyd@VM-4-13-centos linux_gitcode]$ cat .git/HEAD
ref: refs/heads/master

找到默认的master分支:

其中存放的一串ID其实就是当前最新的 commit id,可以理解为一个git对象。

3、objects为Git的对象库,里面包含了创建的各种版本库对象及内容。

当执行命令git add时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,就位于".git/objects"目录下。

查找object时要将分成2部分,其前2位是文件夹名称,后38位是文件名称。

比如上面查到的 68df79a6f2a582fd8f390eaa947577b898bc2069 ,即说明它位于 68 文件夹下。

找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过sha(安全哈希算法)加密过的文件,好在我们可以使用git cat-file命令来查看版本库对象的内容:

[wyd@VM-4-13-centos linux_gitcode]$ git cat-file -p 68df79a6f2a582fd8f390eaa947577b898bc2069
tree 82a432cf4469d279b2ec65a226fbbb5c19fb56c9
parent 1853b26b95891348de92982b34f3bdbdfa01e049
author wyd <xxxxxxxxxx@qq.com> 1701610873 +0800
committer wyd <xxxxxxxxxx@qq.com> 1701610873 +0800一次性提交3个文件

其中,还有一行tree 82a432cf4469d279b2ec65a226fbbb5c19fb56c9,使用同样的方法查看:

[wyd@VM-4-13-centos linux_gitcode]$ git cat-file -p 82a432cf4469d279b2ec65a226fbbb5c19fb56c9
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad        ReadMe
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391        file1
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391        file2
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391        file3

再看 ReadMe 对应的 3b18e512dba79e4c8300dd08aeb37f8e728b8dad

[wyd@VM-4-13-centos linux_gitcode]$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world# 这是我们对ReadMe做的修改!!被git记录了下来!!

每一次提交的修改都会被git以对象的方式记录下来。

总结一下,在本地的git仓库中,有几个文件或者目录很特殊

  • index:暂存区,git add后会更新该内容。

  • HEAD:默认指向master分支的一个指针。

  • refs/heads/master:文件里保存当前master分支的最新commit id(索引,对应的是git对象,对象被维护在objects中)。

  • objects:包含了创建的各种版本库对象及内容,可以简单理解为放了git维护的所有修改。

后面再学习过程中,最好能将常见的git操作与.git目录当中的结构内容变化对应起来,这样有利于我们理解git细节流程。

3.添加文件--场景二

学习到这里,我们已经清楚了如何向仓库中添加文件,并且对于工作区、暂存区、版本库也有了一定的认识。这里再展示一种添加文件的场景,能加深我们对工作区、暂存区、版本库的理解:

tjfz@139-159-150-152:~/gitcodes touch file4    #1.新增file4文件
tjfz@139-159-150-152:~/gitcodes git add file4    #2.将file4添加到暂存区
tjfz@139-159-150-152:~/gitcodes touch file5    #3.新增file5文件
tjfz@139-159-150-152:~/gitcodes git commit -m "add file"    #4.提交修改
[master 3d406co] add file
1 file changed, insertions(+), deletions(-)
create mode 100644 file4

提交后发现打印了 1 file changed,0 insertions(+),0 deletions(-),意思是只有一个文件改变了,这时我们提出了疑问,不是新增了两个文件吗?

再来回忆下,git add file5,file5 就不在暂存区中维护,所以我们 commit 的时候其实只是把已经在暂存区的file4提交了,而遗漏了工作区的file5。

如何提交file5呢?很简单,再次addcommit即可。

4.修改文件

Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。

什么是修改?新增、删除、更改了某些字符都是修改。

objects存储的git对象记录的就是修改的工作区中的内容。

让我们将ReadMe文件进行一次修改:

[wyd@VM-4-13-centos linux_gitcode]$ echo wonderful! > ReadMe
[wyd@VM-4-13-centos linux_gitcode]$ cat ReadMe
wonderful!

此时,仓库中的ReadMe和我们工作区的ReadMe是不同的,如何查看当前仓库的状态呢?

git status命令用于查看在上次提交之后是否有对文件进行再次修改。

[wyd@VM-4-13-centos linux_gitcode]$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#        modified:   ReadMe
#
no changes added to commit (use "git add" and/or "git commit -a")

上面的结果告诉我们,ReadMe被修改过了,但还没有完成添加与提交。

目前,我们只知道文件被修改了,如果能知道具体哪些地方被修改了,就更好了。此时可以用 git diff命令:

[wyd@VM-4-13-centos linux_gitcode]$ git diff ReadMe
diff --git a/ReadMe b/ReadMe
index 3b18e51..af3b811 100644
--- a/ReadMe
+++ b/ReadMe
@@ -1 +1 @@
-hello world
+wonderful!

git diff [file]命令用来显示暂存区工作区文件的差异,显示的格式正是Unix通用的diff格式。

再修改一下 ReadMe 文件:

[wyd@VM-4-13-centos linux_gitcode]$ cat ReadMe
wonderful!wonderful1!
wonderful2!
wonderful3!

git diff 一下,对比暂存区(之前add过的版本)和工作区(刚修改的版本)的ReadMe文件区别:

[wyd@VM-4-13-centos linux_gitcode]$ git diff ReadMe
diff --git a/ReadMe b/ReadMe
index 3b18e51..6a2ca8c 100644
--- a/ReadMe
+++ b/ReadMe
@@ -1 +1,5 @@
-hello world
+wonderful!
+
+wonderful1!
+wonderful2!
+wonderful3!

也可以使用git diff HEAD -- [file]命令来查看本地仓库和工作区文件的区别。

知道了对ReadMe做了什么修改后,再把它提交到本地仓库就放心多了。

[wyd@VM-4-13-centos linux_gitcode]$ git add ReadMe
[wyd@VM-4-13-centos linux_gitcode]$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#        modified:   ReadMe
#

git add 之后,就没有看到上面 no changes added to commit (use "git add" and/or "git commit -a") 的消息了。接下来让我们继续 git commit 即可。

[wyd@VM-4-13-centos linux_gitcode]$ git commit -m '提交修改后的文 件'
[master 2d511b4] 提交修改后的文件1 file changed, 5 insertions(+), 1 deletion(-)

5-版本回退 reset

Git能够管理文件的历史版本,这也是版本控制器重要的能力。

如果有一天你发现之前前的工作做的出现了很大的问题,需要在某个特定的历史版本重新开始,那么这个时候,就需要版本回退的功能了。

执行git reset命令用于回退版本,可以指定退回某一次提交的版本。

“回退”本质是要将本地仓库中的内容进行回退,工作区或暂存区是否回退由命令参数决定。

git reset命令的语法格式为:git reset [--soft | --mixed | --hard] [HEAD]

  • --mixed 为默认选项,使用时可以不用带该参数。该参数将暂存区的内容退回为指定提交版本内容,工作区文件保持不变。

  • --soft 参数对于工作区和暂存区的内容都不变,只是将本地仓库回退到某个指定版本。

  • --hard 参数将工作区和暂存区都退回到指定版本。

    • 切记工作区有未提交的代码时不要用这个命令,因为工作区也会回滚,你没有提交的代码就再也找不回了,所以使用该参数前一定要慎重。

  • HEAD参数说明:

    • 可直接写成commit id,表示指定退回的版本

    • HEAD表示当前版本

    • HEAD^上一个版本

    • HEAD^^上上一个版本

    • 以此类推……

  • 可以使用 ~数字 表示:

    • HEAD~0 表示当前版本

    • HEAD~1 上一个版本

    • HEAD^2 上上一个版本

    • 以此类推……

回退功能演示:

执行命令 git reset --hard 58d0aa3 后,可见工作区、暂存区和本地仓库的内容都回退到了第一版本的样子,HEAD指针也更改的指向,指向了第一版本的commitID58d0aa3。且 git log --pretty=oneline 打印日志可见,只剩下操作第一版本时的日志,中间添加各种file的日志也没有了。

如果后悔了,还想从第一版本58d0aa3恢复到回滚前的999cead版本呢?同样的操作,git reset --hard 999cead,工作区、暂存区和本地仓库都回滚到了原来版本999cead的样子。

可见,只有拿到某一版本的commitID,才能通过reset命令实现回滚操作。

但是上述情况下,我们能从第一版本回滚到原来版本,是因为我们在还在原来版本时就打印了一下log,知道了原来版本的commitID。如果我们没有打印过原来版本的commitID,不就不能从第一版本又回退到原来版本了呢?

也就是说,如果从一个新版本回退到旧版本,但后悔了,又想回到一个新版本,在旧版本时git log肯定是拿不到想要的新版本的commitID的,这时还有一个补救的方法:git reflog,该命令能记录到本地的每一次命令:

这样,你就可以很方便的找到你的所有操作记录了,但第一列的一串数字是啥东西?

这个也是各个版本的 commit id 的部分。没错,Git 版本回退的时候,也可以使用部分 commit id 来代表目标版本。

可往往理想很丰满,现实很骨感。在实际开发中,突然某一天,我又想回退到某个版本,可由于开发的时间长了,commit id早就找不到了,那该如何操作呢?貌似现在不可能了……

值得说的是,Git 的版本回退速度非常快,因为 Git 在内部有个指向当前分支(此处是master)的HEAD 指针, refs/heads/master文件里保存当前 master 分支的最新 commit id 。

当我们在回退版本的时候,Git 仅仅是给refs/heads/master 中更换一个存储的version(即commitID),可以简单理解成如下示意图:

6-撤销修改

如果我们在我们的工作区写了很长时间代码,越写越写不下去,觉得自己写的实在是垃圾,想恢复到上一个版本。

情况一:对于工作区的代码,还没有add

你当然可以直接删掉你目前在工作区新增的代码,像这样:

# 向ReadMe中新增一行代码
hyb@139-159-150-152:~/gitcode$ git status
On branch master
nothing to commit, working tree clean
hyb@139-159-150-152:~/gitcode$ vim ReadMe 
hyb@139-159-150-152:~/gitcode$ cat ReadMe 
hello bit
hello git
hello world
hello version1
hello version2
hello version3
This piece of code is like shit #新增代码# 查看状态
hyb@139-159-150-152:~/gitcode$ git status
On branch master
Changes not staged for commit: 
(use "git add <file>..." to update what will be committed) 
(use "git restore <file>..." to discard changes in working directory) modified: ReadMeno changes added to commit (use "git add" and/or "git commit -a")# 直接删除代码 恢复原来的样子
hyb@139-159-150-152:~/gitcode$ vim ReadMe 
hyb@139-159-150-152:~/gitcode$ cat ReadMe 
hello bit
hello git
hello world
hello version1
hello version2
hello version3
hyb@139-159-150-152:~/gitcode$ git status
On branch master
nothing to commit, working tree clean

辛亏我们工作效率不高,才写了一行代码就发现不行了,要是你写了3天,一直都没有提交,该怎么删掉呢?你自己都忘了自己新增过哪些。

有同学说,我可以 git diff xxx 一下,看看差别在删啊,那你肯定又要花3天时间删代码了,并且很大的概率还会改出bug。一周过去了,你怎么向你的老板交代呢?

Git 其实还为我们提供了更好的方式,我们可以使用git checkout -- [file]命令让工作区的文件回到最近一次 add 或 commit 时的状态。

要注意 git checkout -- [file] 命令中的--很重要,切记不要省略,一旦省略,该命令就变为其他意思了,后面我们再说。示例如下:

情况二:已经add,但没有commit

如果已经给代码执行了add,保存到了暂存区,该怎么撤销呢?

让我们来回忆一下学过的 reset 回退命令:

该命令如果使用 --mixed 参数,可以将暂存区的内容退回为指定版本的本地仓库的内容,但工作区文件保持不变。这就达成了回退暂存区的效果,并且把当前的情况二转换成了上面的情况一,此时再要回退工作区使工作区的内容和暂存区一致,使用 git checkout -- ReadMe 命令即可。(当然,要完成工作区和暂存区的同时回退,也可以直接使用 --hard 选项,这样只需要一行代码,这里不做演示。)

示例如下:

注意:git reset HEAD 就是回到当前版本的意思(如果要回到上一版本,写作HEAD^)

git status查看一下,发现现在暂存区是干净的,只有工作区有修改。

丢弃工作区的修改:

恢复了!

情况三:已经add,并且也commit了

不要担心,我们可以 git reset --hard HEAD^回退到上一个版本。

  • --hard:同时将本地仓库、工作区、暂存区都回退到上一版本。

  • HEAD^:上一版本的写法。

不过,前提条件是你还没有把自己的本地仓库push到远程仓库。

事实上,撤销的目的就是让本地仓库的代码不影响远程仓库的代码。

还记得Git是分布式版本控制系统吗?我们后面会讲到远程版本库,一旦你推送到远程版本库,你就真的惨了……

准备工作:add、commit

回退操作:将本地仓库内容回退到上一版本,且同步至工作区、暂存区。

7-删除本地仓库中的文件

在Git中,删除也是一个修改操作。

如果要删除本地仓库中的文件,怎么操作呢?

方法一:先在工作区中正常 rm file5,然后把工作区删除操作add file5到暂存区、commit到本地仓库。

在工作区中的修改(修改也包括删除操作)add到暂存区中后,暂存区会提示 file5 被删除,再 commit的时候这个删除的操作和结果也会被同步到本地仓库。

方法二:git rm file 命令直接将 file 从工作区和暂存区中一同删除,然后直接 commit 到本地仓库。


**小结

本篇涉及的部分git命令:

git init:初始化git仓库

git config:配置git配置项

git config -l:查看配置项

git config --unset:删除配置项

git add:添加工作区的内容到暂存区

git commit:提交暂存区中的内容到版本库

git log:查看历史提交记录

git cat-file:查看版本库对象的内容

git status:查看仓库状态

git diff:显示文件差异

git reset:版本回退

**下篇内容

五、分支管理

六、远程操作

七、标签管理

八、多人协作

九、企业级开发模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序踩坑,skyline模式下,scroll-view下面的一级元素设置margin中的auto无效,具体数据有效

开发工具版本 基础库 开启skyline渲染调试 问题描述 skyline模式下,scroll-view下面的一级元素的margin写auto的值是没有效果的(二级元素margin写auto是有效果的),关闭这个模式就正常显示 演示效果图 父元素的宽度和高度效果(宽度是750rpx,宽度占满的) 一级元素宽度和css效果…

Python游戏制作大师,Pygame库的深度探索与实践

写在前言 hello&#xff0c;大家好&#xff0c;我是一点&#xff0c;专注于Python编程&#xff0c;如果你也对感Python感兴趣&#xff0c;欢迎关注交流。 希望可以持续更新一些有意思的文章&#xff0c;如果觉得还不错&#xff0c;欢迎点赞关注&#xff0c;有啥想说的&#x…

笔记3:torch训练测试VGG网络

&#xff08;1&#xff09;利用Netron查看网络实际情况 上图链接 python生成上图代码如下&#xff0c;其中GETVGGnet是搭建VGG网络的程序GETVGGnet.py&#xff0c;VGGnet是该程序中的搭建网络类。netron是需要pip安装的可视化库&#xff0c;注意do_constant_foldingFalse可以防…

【简单介绍下Sass】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Windows 查找端口号关闭端口号关闭进程的操作流程

Windows 查找端口号关闭端口号关闭进程 8000为端口号 1.查看端口占用程序的ID号 netstat -aon|findstr "8000"比如结果是5684 2.查看ID对应的程序进程 tasklist|findstr "6884"3.关闭进程 taskkill -PID 6884 -F成功: 已终止 PID 为 5684 的进程。

华为机试打卡 HJ2 计算某字符出现次数

要机试了&#xff0c;华孝子求捞&#xff0c;功德 描述 写出一个程序&#xff0c;接受一个由字母、数字和空格组成的字符串&#xff0c;和一个字符&#xff0c;然后输出输入字符串中该字符的出现次数。&#xff08;不区分大小写字母&#xff09; 数据范围&#xff1a; 1≤&a…

【复杂网络】如何用简易通俗的方式快速理解什么是“相对重要节点挖掘”?

什么是相对重要节点&#xff1f; 一、相对重要节点的定义二、如何区分相对重要节点与重要节点&#xff1f;1. 相对重要性与节点相似性2. 识别相对重要节点的两个阶段第一阶段&#xff1a;个体重要性值的计算第二阶段&#xff1a;累积重要性值的计算 三、相对重要节点挖掘算法1.…

条件变量解决同步问题之打印金鱼

说明 本代码为jyy老师上课演示条件变量解决同步问题示例(本人只做记录与分享) 本人未使用老师封装的POSIX线程库, 直接在单文件中调试并注释 问题描述 有三类线程 T1 若干: 死循环打印< T2 若干: 死循环打印> T3 若干: 死循环打印_ 任务: 对线程同步&#xff0c;使得屏幕…

ASP.NET一种基于C2C模式的网上购物系统的设计与实现

摘 要 网络购物已经慢慢地从一个新鲜的事物逐渐变成日常生活的一部分&#xff0c;以其特殊的优势而逐渐深入人心。本课题是设计开发一种基于C2C模式的网上购物系统。让各用户使用浏览器进行商品浏览。注册用户可以轻松的展示自己的网络商店&#xff0c;能对自己的用户信息进行…

Vagrant + docker搭建Jenkins 部署环境

有人问&#xff0c;为什么要用Jenkins&#xff1f;我说下我以前开发的痛点&#xff0c;在一些中小型企业&#xff0c;每次开发一个项目完成后&#xff0c;需要打包部署&#xff0c;可能没有专门的运维人员&#xff0c;只能开发人员去把项目打成一个war包&#xff0c;可能这个项…

钉钉群定时发送消息1.0软件【附源码】

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 有时候需要在钉钉群里提醒一些消息。要通知的群成员又不方便用定时钉的功能&#xff0c;所以写了这么一个每日定时推送群消息的工具。 易语言程序&#xff0c;附上源码与模块&#x…

C++中vector的简单实现

文章目录 一、主要任务1. 查看文档的网站的链接2.内部模拟的函数 二、本人的模拟实现过程1. 所需模拟实现的函数a.构造、拷贝构造b. reverse()扩容c.insert()、push_back()插入数据d. erase()、pop_back()删除数据e. swap()交换f. begin()、end()非const与const迭代器g. 完善构…

mysql的存储结构

一个表就是一个ibd文件 .ibd文件大小取决于数据和索引&#xff0c;在5.7之后才会为每个表生成一个独立表空间即一个ibd文件&#xff0c;在此之前&#xff0c;所有表默认下都会存储在“系统表空间”&#xff08;共享表空间&#xff09;&#xff0c;所有表都在一个ibd文件。 inn…

示例六、湿敏传感器

通过以下几个示例来具体展开学习,了解湿敏传感器原理及特性&#xff0c;学习湿敏传感器的应用&#xff1a; 示例六、湿敏传感器 一、基本原理&#xff1a;随着人们生活水平的不断提高&#xff0c;湿度监控逐步提到议事日程上。由于北方地区秋冬季干燥&#xff0c;需要控制室内…

16.接口自动化学习-编码处理与装饰器

1.编码和解码 编码&#xff1a;将自然语言翻译成计算机可以识别的语言 hello–01010 解码&#xff1a;将机器识别的语言翻译成自然语言 2.编码格式 UTF-8 GBK unicode 3.编码操作 #编码操作str1"hello呀哈哈哈"str2str1.encode(gbk)print(str2)print(type(str2))…

js原型链与继承笔记

前置阅读&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain js中的“类”是一个函数。function test() {}中&#xff0c;test是由Function生成的。prototype与__proto__的区别&#xff1a; 前者是js函数&#xff08;C…

Linux学习之路 -- 文件系统 -- 缓冲区

前面介绍了文件描述符的相关知识&#xff0c;下面我们将介绍缓冲区的相关知识。 本质上来说&#xff0c;缓冲区就是一块内存区域&#xff0c;因为内核上的缓冲区较复杂&#xff0c;所以本文主要介绍C语言的缓冲区。 目录 1.为什么要有缓冲区 2.应用层缓冲区的默认刷新策略 …

如何在bud里弄3d模型?---模大狮模型网

随着数字化设计的不断发展&#xff0c;越来越多的设计软件提供了对3D模型的支持&#xff0c;为设计师们带来了更广阔的创作空间。Bud作为一款功能强大的设计工具&#xff0c;也提供了添加和编辑3D模型的功能&#xff0c;让用户能够更加灵活地进行设计创作。本文将为您详细介绍如…

【计算机网络】计算机网络体系结构

&#x1f6a9;本文已收录至专栏&#xff1a;计算机网络学习之旅 一.常见的三种结构 (1) OSI参考模型 为了使不同体系结构的计算机网络都能互连起来&#xff0c;国际标准化组织于1977年成立了专门机构研究该问题&#xff0c;提出了著名的开放系统互连基本参考模型&#xff0c…

pycharm 将项目连同库一起打包及虚拟环境的使用

目录 一、创建虚拟环境 1、用 anaconda 创建 2、Pycharm 直接创建 二、虚拟环境安装第三方库 1、创建项目后&#xff0c;启动终端(Alt F12)&#xff0c;或者点击下方标记处。 2、使用 pip 或者 conda 来进行三方库的安装或卸载 3、将项目中的库放入文档&#xff0c;便于…