git基本理论和操作

git基本理论

  1. git工作区域

    Git本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。如果在加上远程的git仓库(Remote Directory)就可以分为四个工作区域。文件在这四个区域之间的转换关系如下:

    • Workspace:工作区,就是你平时存放项目代码的地方
    • Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
    • Repository:仓库区(或本地仓库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
    • Remote:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换

    本地的三个区域确切的说应该是git仓库中HEAD指向的版本

    • Directory:使用Git管理的一个目录,也就是一个仓库,包含我们的工作空间和Git的管理空间。
    • WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间。
    • .git:存放Git管理信息的目录,初始化仓库的时候自动创建。
    • Index/Stage:暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区。
    • Local Repo:本地仓库,一个存放在本地的版本库;HEAD会只是当前的开发分支(branch)。
    • Stash:隐藏,是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态。
  2. git 工作流程

    git的工作流程一般是这样的:

    ​ 1、在工作目录中添加、修改文件;

    ​ 2、将需要进行版本管理的文件放入暂存区域;

    ​ 3、将暂存区域的文件提交到git仓库。

    因此,git管理的文件有三种状态:已修改(modified),已暂存(staged),已提交(committed)

  3. 图解教程

个人认为Git的原理相比别的版本控制器还是复杂一些的,有一份图解教程比较直观:

git基本操作操作(git bash命令操作)

  1. 创建工作目录与常用指令

    工作目录(WorkSpace)一般就是你希望Git帮助你管理的文件夹,可以是你项目的目录,也可以是一个空目录,建议不要有中文。

    日常使用只要记住下图6个命令:

  2. 、获得GIT仓库

    ​ 创建本地仓库的方法有两种:一种是创建全新的仓库,另一种是克隆远程仓库。

    • 创建全新仓库

      ​ 进入git bash创建新的仓库:

      # 在当前目录新建一个Git代码库
      $ git init

      刚刚创建的git代码库 .git目录如下所示:

      执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。

      当然如果使用如下命令,可以把创建目录与仓库一起完成:

      # 新建一个目录,将其初始化为Git代码库
      $ git init [project-name]

    • 克隆远程仓库

      可以从github和gitee上克隆远程的仓库.

      如fastjson的码云远程仓库地址:https://gitee.com/wenshao/fastjson

      在git bash命令行执行 git clone https://gitee.com/wenshao/fastjson就可以将远程仓库的代码拉下来

  3. git文件操作

​ 版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。GIT不关心文件两个版本之间的具体差别,而是关心文件的整体是否有改变,若文件被改变,在添加提交时就生成文件新版本的快照,而判断文件整体是否改变的方法就是用SHA-1算法计算文件的校验和。

3.1 文件4种状态

  • Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.

  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件

  • Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改

  • Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

 3.2 查看文件的状态

 ```
 # 查看所有文件的状态
 git status
 # 查看指定文件的状态
 git status filename
 ```

 3.3  添加文件与目录

 工作区(Working Directory)就是你在电脑里能看到的目录。

 版本库(Repository)工作区有一个隐藏目录`.git`,这个不算工作区,而是Git的版本库。

 Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支`master`,以及指向`master`的一个指针叫`HEAD`。

 将untracked状态的文件添加到暂存区,语法格式如下:

 ```linux
 # 添加指定文件到暂存区
 $ git add [file1] [file2] ...
 
 # 添加指定目录到暂存区,包括子目录
 $ git add [dir]
 
 # 添加当前目录的所有文件到暂存区
 $ git add .
 ```

 3.4 移除文件与目录

![](https://img2018.cnblogs.com/blog/1389886/201911/1389886-20191116145850119-1894528153.png)

 当执行如下命令时,会直接从暂存区删除文件,工作区则不做出改变

 ```linux
 #直接从暂存区删除文件,工作区则不做出改变
 git rm --cached <file>
 ```

 通过重写目录树移除add文件:

 ```
 #如果已经用add 命令把文件加入stage了,就先需要从stage中撤销
 git reset HEAD <file>...
 ```

 当执行 “git reset HEAD” 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

 移除所有未跟踪文件

 ```
 #移除所有未跟踪文件
 #一般会加上参数-df,-d表示包含目录,-f表示强制清除。
 git clean [options] 
 #只从stage中删除,保留物理文件
 git rm --cached readme.txt 
 
 #不但从stage中删除,同时删除物理文件
 git rm readme.txt 
 
 #把a.txt改名为b.txt
 git mv a.txt b.txt 
 ```

当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。

当执行 “git reset HEAD” 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

当执行 “git rm –cached ” 命令时,会直接从暂存区删除文件,工作区则不做出改变。

当执行 “git checkout .” 或者 “git checkout — ” 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。

当执行 “git checkout HEAD .” 或者 “git checkout HEAD ” 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改 动。

3.5 文件比较

​ git diff [文件名]:将工作区中的文件和暂存区进行比较
git diff [本地库中历史版本] [文件名]:将工作区中的文件和本地库历史记录比较
​ 不带文件名比较多个文件

3.6 文件签出

如果仓库中已经存在文件f4.txt,在工作区中对f4修改了,如果想撤销可以使用checkout,签出覆盖

检出命令git checkout是git最常用的命令之一,同时也是一个很危险的命令,因为这条命令会重写工作区

语法:

#用法一
git checkout [-q] [ ] [--] ...
#用法二
git checkout [ ]
#用法三
git checkout [-m] [[-b]--orphan] ] [ ]

$ git checkout branch
#检出branch分支。要完成图中的三个步骤,更新HEAD以指向branch分支,以及用branch 指向的树更新暂存区和工作区。

$ git checkout
#汇总显示工作区、暂存区与HEAD的差异。

$ git checkout HEAD
#同上

$ git checkout -- filename
#用暂存区中filename文件来覆盖工作区中的filename文件。相当于取消自上次执行git add filename以来(如果执行过)的本地修改。

$ git checkout branch -- filename
#维持HEAD的指向不变。用branch所指向的提交中filename替换暂存区和工作区中相 应的文件。注意会将暂存区和工作区中的filename文件直接覆盖。

$ git checkout -- . 或写作 git checkout .
#注意git checkout 命令后的参数为一个点(“.”)。这条命令最危险!会取消所有本地的 #修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件,不给用户任何确认的机会!

$ git checkout commit_id -- file_name
#如果不加commit_id,那么git checkout -- file_name 表示恢复文件到本地版本库中最新的状态。

3.7 提交

通过git add 只是将文件或目录添加到index缓存区,使用commit可以实现将暂存区的文件提交到本地仓库。

# 提交暂存区到仓库区
$ git commit -m [message]

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

# 提交工作区自上次commit之后的变化,直接到仓库区,跳过了add,对新文件无效
$ git commit -a

# 提交时显示所有diff信息
$ git commit -v

# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]

# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...

修订提交

如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过"git add"添加到暂存区,然后执行以下命令:

#修订提交
git commit --amend

撤销提交(commit)

原理就是放弃工作区和index的改动,同时HEAD指针指向前一个commit对象

#撤销上一次的提交
git reset --hard HEAD~1

要通过git log查看提交日志,也可直接指定提交编号或序号

撤销提交
git revert <commit-id>
这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。

3.8 日志

查看提交日志可以使用git log指令,语法格式如下:

#查看提交日志
git log [<options>] [<revision range>] [[\--] <path>…?]

"git log --graph"以图形化的方式显示提交历史的关系,这就可以方便地查看提交历史的分支信息,当然是控制台用字符画出来的图形。

"git log -1"则表示显示1行。

使用history可以查看您在bash下输入过的指令:

3.9 查看所有分支日志

"git reflog"中会记录这个仓库中所有的分支的所有更新记录,包括已经撤销的更新。

3.10 查看文件列表

使用git ls-files指令可以查看指定状态的文件列表,格式如下:

#查看指定状态的文件
git ls-files [-z] [-t] [-v] (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])* (-[c|d|o|i|s|u|k|m])*

3.11 撤销更新

  • 撤销暂存区更新

    使用"git add"把更新提交到了暂存区。这时"git status"的输出中提示我们可以通过"git reset HEAD ..."把暂存区的更新移出到WorkSpace中

  • 撤销本地仓库更新

    使用git log 查看提交日志,撤销提交有两种方式: 使用HEAD指针和使用commit id

    在Git中,有一个HEAD指针指向当前分支中最新的提交。当前版本,我们使用"HEAD^",那么再钱一个版本可以使用"HEAD^^",如果想回退到更早的提交,可以使用"HEAD~n"。(也就是,HEAD^=HEAD~1,HEAD^^=HEAD~2).

    git reset --hard HEAD^
    git reset --hard HEAD~1
    git reset --59cf9334cf957535cb328f22a1579b84db0911e5(commit id)

3.12 删除文件

  • 删除未跟踪文件

    如果文件还是未跟踪状态,直接删除文件就可了,bash中使用rm可以删除文件,rm filename

  • 删除已提交文件

    ​ git rm -f filename -f 强制删除,物理删除了,同时删除工作区和暂存区中的文件

  • 撤销删除

    git checkout filename

  1. 分支

分支在GIT中相对较难

分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN。

如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

Git分支的速度非常快。

截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支

分支中常用命令:

# 列出所有本地分支
$ git branch

# 列出所有远程分支
$ git branch -r

# 列出所有本地分支和远程分支
$ git branch -a

# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]

# 新建一个分支,并切换到该分支
$ git checkout -b [branch]

# 新建一个分支,指向指定commit
$ git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]

# 切换到指定分支,并更新工作区
$ git checkout [branch-name]

# 切换到上一个分支
$ git checkout -

# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支
$ git merge [branch]

# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]

# 删除分支
$ git branch -d [branch-name]

# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]

分支合并(git merge):

过程描述:
(1) 创建一个远程仓库;
(2) 本地拉取远程仓库的代码到master分支,并在本地创建develop分支用于开发.
(3) 将本地develop分支修改git commit到本地的master分支;
(4) 如果此时远程仓库的代码进行了修改,而我们本地的master未同步远程仓库就会出现代码冲突问题,因为本地的master和远程的master都进行了修改,此时就应该进行合并分支;
(5) 将远程仓库的最新代码拉取到本地master,本地master进行git merge操作,解决代码冲突问题,合并分支,进行提交到远程仓库;

猜你喜欢

转载自www.cnblogs.com/startway/p/11871875.html