专栏首页码神路漫漫从文件生命周期看GIT的提交流程

从文件生命周期看GIT的提交流程

紧接上篇,今天从实在操作方面说一下GIT使用中,使用最多的流程-提交到仓库。开始说明提交流程之前,可以先去看一下上篇提到的GIT整体架构图。本章说的内容是上面这张图的前面部分,如下:

只有提交本地仓库的流程,并没有涉及到远程仓库。关于提交流程,常用的命令:add和commit,add负责提交到暂存区,commit提交到仓库。但并不是只有这两个命令就足够了。

在开始之前,我们先需要做一些初始化工作。

操作系统:centos7 GIT版本: 1.8.3.1。

配置环境

提交git仓库,需要做两个基本的配置操作:

$ git config --global user.name poloxue
$ git config --global user.email poloxue123@163.com

配置姓名与邮箱地址。关于git配置还有很多内容,本章内容重点不在于此,就不作过多详解。

准备仓库

首先我们需要一个git仓库,两个命令可以实现: init 和 clone。 git init,是通过初始化本地目录的方式创建仓库。 首先,创建一个测试的文件夹。执行初始化操作,查看文件夹变化,如下:

$ mkdir experiment
$ cd experiment/
$ git init

初始化空的 Git 版本库于 /home/vagrant/work/git/experiment/.git/

$ ls -a
. .. .git

文件夹下多出了一个.git的文件,上面一节对.git有过简单说明。我们的暂存区和本地仓库就是存在于这个文件下面。

git clone,通过远程克隆方式获取版本库。本人刚开始使用git的时候,以为git像svn一样需要依赖远程,获取仓库首先想到的是去github上面clone。

clone的使用很简单,我们通过克隆goquery的源码来演示,如下:

$ git clone https://github.com/PuerkitoBio/goquery.git
Cloning into 'goquery'...
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 1212 (delta 2), reused 8 (delta 2), pack-reused 1204
Receiving objects: 100% (1212/1212), 434.03 KiB | 49.00 KiB/s, done.
Resolving deltas: 100% (697/697), done.
Checking connectivity... done.
$ ls -a
.                       bench_array_test.go     expand.go               property.go
..                      bench_example_test.go   expand_test.go          property_test.go
.git                    bench_expand_test.go    filter.go               query.go
.gitattributes          bench_filter_test.go    filter_test.go          query_test.go
.gitignore              bench_iteration_test.go go.mod                  testdata
.travis.yml             bench_property_test.go  go.sum                  traversal.go
LICENSE                 bench_query_test.go     iteration.go            traversal_test.go
README.md               bench_traversal_test.go iteration_test.go       type.go
array.go                doc                     manipulation.go         type_test.go
array_test.go           doc.go                  manipulation_test.go    utilities.go
bench                   example_test.go         misc                    utilities_test.go

提交流程

从文件生命周期看提交流程,首先一个文件在整个生命周期可能存在哪些状态,如下:

  • 未追踪 untracked file
  • 已暂存 staged file
  • 未更新 no updated file
  • 已更新 updated file

还是先动手画个图,如下:

上面的图以文件状态的角度出发,指出了一个文件从创建到提交文件仓库再到脱离仓库追踪的整个过程可能经历的各种状态。

在开始正文之前先介绍一下GIT查看仓库中文件状态的命令:git status。如果仓库文件有所变化,执行此命令可以查看各个变化文件状态。

未追踪

在工作目录下新创建的一个文件初始状态处于未追踪。此时文件不受版本系统的控制。 下面在我们之前初始化为git仓库的experiment的工作目录,新建一个README.md。然后随意输入一些内容。使用git status查看一下当前仓库状态,如下:

$ touch "experiment" >> README.md
$ git status
# On branch master
#
# Initial commit
#
# Untracked files
#   (use "git add <file>..." to include in what will be committed)
#
#       README.md
nothing added to commit but untracked files present (use "git add" to track)

此时README.md为untracked file,下面提示 Use "git add ..." to include in what will be committed,即为使用git add命令去添加将被提交的文件。似乎没有说明怎么追踪文件,继续看,如需要被追踪 use "git add" to track, 意为使用git add追踪文件。

已更新

为了下面的内容更方便讲解,先来说说文件的已更新状态。啥叫已更新呢?个人总结,上图中把文件的三种情况都归于已更新:编辑更新,冲突更新,删除更新。下面从这三种更新的角度来谈谈,看看这些更新状态如何产生。

编辑更新

编辑更新就是因我们修改文件而导致的更新。下面看下如何产生一个编辑更新状态的文件。

首先,快速通过以下三步添加一个新文件modify.go到版本库中。

$ touch modify.go
$ git add modify.go
$ git commit -m "new file modify.go"

下面我们修改文件modify.go,添加任意内容修改,git status查看状态:

#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes will working directory)
#
#        modified:   modify.go
#
# no changes added to commit (use "git add" and/or "git commit -a")

此时可以看到modify.go文件为modified状态。使用git时,大多数更新都是属于这种类型。

冲突更新

冲突更新是怎么产生的呢?我们知道GIT支持强大的分支功能,前面说明GIT的优点也提到了这个问题。但是分支就会有一个问题,两个分支同时修改同一文件的同一部分内容,冲突就产生了。下面演示这种类型的更新如何产生?

首先,快速通过以下三步添加一个新文件conflict.go到版本库中。

$ touch conflict.go
$ git add conflict.go
$ git commit -m "new file conflict.go"

创建两个分支:feature

$ git branch feature

在master上conflict.go添加内容: master,在feature上conflict.go添加内容: feature。并都提交到仓库。

在master执行合并操作:

$ git merge feature
Auto-merging conflict.go
CONFLICT (content): Merge conflict in conflict.go
Automatic merge failed; fix conflicts and then commit the result.

可以看到冲突很容易就产生。团队合作开发时,冲突更新也是我们平时最不喜欢遇到的,如果冲突的内容都是自己的,那还好处理。如果涉及了很多人,就会涉及大量的沟通成本。

删除更新

删除也算更新,这个逻辑理解起来有点怪。但删除毕竟改变了文件内容,让文件不存在了,所以也算更新。这种更新如何产生呢?

首先,快速通过以下三步添加一个新文件delete.go到版本库中。

$ touch delete.go
$ git add delete.go
$ git commit -m "new file delete.go"

提交之后,手动删除delete.go文件

$ rm delete.go

此时使用git status查看delete.go文件状态便是删除更新的状态。

已暂存

在上面的1、2两段,关于未追踪和已更新,总结的是工作区文件存在的各种状态。但是在把文件提交到版本之前,还需要中间的一个过渡阶段:暂存区。

文件提交到暂存区便是已暂存状态。看上面文件各个状态之间的转化图,我们知道文件可以由未跟踪和已更新两种状态转化而来。

由之前的操作,现在已经有了各种状态的文件:

  • 未追踪文件:README.md
  • 编辑更新文件:modify.go
  • 冲突更新文件:conflict.go
  • 删除更新文件:delete.go

下面如何使用git add将这些文件添加到暂存区:

  • git add -A 最省事,所有文件添加到暂存区;
  • git add -u 已更新文件添加暂存区,即modify.go conflict.go delete.go;
  • git add . 将除删除更新的其他文件加到暂存区,即README.md modify.go conflict.go;
  • git add * 会忽略.gitignore规则,把本来应忽略文件添加暂存区,慎用;

当不确定时,可直接添加某文件git add filepath;

注:评论区有朋友回复说,他的测试 git add . 会把删除更新加入暂存区,我分别在 git 1.8.3.1 和 2.9.3 两个版本测试了下,新版的确和旧版行为不同,会把删除更新加入到暂存区。

$ git add modify.go;

删除更新也可以使用git rm命令,直接将删除文件提交到暂存区同时删除文件,如需删除提交暂存区但工作区文件保留可使用选项--cached:

$ git rm delete.go
$ git rm delete.go --cached

好!下面把所有文件提交到暂存区:

$ git add -A

此时,git status查看文件状态:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage
#
#      renamed:    delete.go -> README.md
#      modified:   conflict.go
#      modified:   modify.go
#      new file:   new.go

因为同时存在删除和新建,delete.go被认为rename为README.md,正常情况工作区文件状态与暂存区的对应关系如下:

工作区           暂存区
untracked       new file
modified        modified
both modified   modified
deleted         deleted

未更新

怎么让文件转化为未更新状态呢?提交仓库!我们已经把所有内容提交暂存,下面可以借助于commit命令进行仓库提交:

常用方式

提交仓库的常用,执行如下命令:

$ git commit -m "feat: new function"

再查看文件状态,发现已经没有内容可以提交,此时仓库处于未更新的状态。

更新直接提交

git commit -am "message" 

可以将编辑更新直接从工作区提交仓库,即跨过暂存区。不支持删除与冲突更新和新文件的提交。

提交修订

如提交有误,支持对当前提交进行修订。

$ git commit --amend

有什么作用?可用来修改提交日志;在提交漏提交文件时,仍保持为一个提交。

总结

本文主要从GIT文件的生命周期来看整个提交流程。为了便于理解,自己总结了编辑更新、删除更新、冲突更新几个新词,希望不会造成误解。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • go语言学习-位运算

    Go语言的大多数位运算符与C语言都比较类似,除了取反在C语言中是~x,而在Go语言中 是^x

    solate
  • mac 上安装Protobuffer

    Protocol Buffers (ProtocolBuffer/ protobuf )是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序...

    solate
  • go 格式化输出

      fmt 包实现了格式化 I/O 函数,类似于 C 的 printf 和 scanf。格式“占位符”衍生自 C,但比 C 更简单。

    solate
  • go基础入门(六)

    上篇文章我们简易学了struct今天我们来继续深入的理解一下struct,为了更好的学些struct我们今天首选要先了解一下interface。

    大话swift
  • go语言学习-类型转换

    1.字符串到整形(string to int):ParseInt 返回的是 int64

    solate
  • go语言学习-未分类的一些记录 原

    它是一个语法糖(syntactic sugar),即这种语法对语言的功能并没有影响,但是更方便程序员使用。通 常来说,使用语法糖能够增加程序的可读性,从而减少程...

    solate
  • Gin框架详解

    gin是一个开源的,用golang开发的web框架,https://github.com/gin-gonic/gin 地址如下。它有如下特性:

    榴莲其实还可以
  • Bystack跨链技术源码解读

    Bystack是由比原链团队提出的一主多侧链架构的BaaS平台。其将区块链应用分为三层架构:底层账本层,侧链扩展层,业务适配层。底层账本层为Layer1,即为目...

    比原链Bytom
  • go 编译执行文件分发

    今天咱们不说go的语法知识,为什么不说语法了呢?因为咱们做了这么就的go东西全是在编辑器中运行的,大家是不是很想知道怎么在编辑器之外去执行go程序呢?(win的...

    大话swift
  • Golang常见的坑笔记

    Format 的时候 时间必须是 2006-01-02 15:04:05 ,奇葩时间。

    solate

扫码关注云+社区

领取腾讯云代金券