这些git的基本操作,你真的会了吗?

407 阅读7分钟

Git使用指南

一. Git的基本使用

1.简介

略....

2.安装

git-scm.com/book/zh/v2

2.1 git使用之前的最小配置

git config --global user.name "your_name"
git config --global user.email "your_email@domain.com"

config的三个作用域

  • git config --local:local只对某个仓库有效
  • git config --global:global对当前用户所有仓库有效
  • git config --system:对系统所有登陆的用户有效

查看所有配置

git config --list
git config --list --global

3.创建版本库

3.1 新建文件夹 mkdir 文件夹名

$ mkdir testFile
$ cd testFile
$ pwd
  • pwd 命令用于显示该文件的存放位置
  • 注意:如果是Windows系统,为了避免各种莫名其妙的问题,请确保目录名不包含中文

3.2 初始化仓库:git init

$ git init
$ ls -ah
  • ls -ah命令是用来查看隐藏目录的,使用该命令就能看到隐藏的 .git目录

3.3 编写文件,上传git

$ vi readme.txt
//...此处省略文件内容的书写,书写完内容按ESC退出编写模式,然后输入 :wq保存退出
$ git add reademe.txt
$ git commit -m "it is just a practice"
[master (root-commit) 743c5af] wrote a simple description
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt
  • vi readme.txt:创建文件并进入编写模式
  • git add readme.txt:把文件添加到仓库
  • git commit -m "description":提交代码并添加改动描述
  • 提交成功之后会返回文件修改数量,和文件改动情况
  • 还可以一次性添加多个文件到仓库,然后一次提交
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files"
  • 小结
    • git init 用来初始化仓库
    • git add 文件名 用来添加文件到仓库
    • git commit -m "description" 用来提交代码
    • vi 文件名 当文件不存在的时候,创建文件并且进入编写模式,当文件存在的时候,编写文件
    • 注意,编辑文件的时候,使用i键开始编辑,编辑结束之后,使用ESC键退出编辑模式,然后使用 :wq保存文件并退出

4. 时光穿梭机

4.1 查看git 状态区别

  • git status:查看工作区的状态
  • git diff:查看修改的内容
  • 演示
    1. 进去 readme.txt,修改文件并保存退出
    2. 使用 git status 查看工作区状态,告诉我们文件被修改但是没提交
    3. 使用 git diff 查看修改,会详细显示修改情况
    4. 提交修改到仓库 git add readme.txt
    5. 查看工作区状态 git status,改动已被提交到仓库
    6. 提交代码 git commit -m "some modify",显示修改行数信息
    7. 查看状态 git status,显示没有文件被提交,工作区是干净的
    8. 注意观察修改过程中几次调用 git status 返回的区别

4.2 版本回退

  • git log:查看提交日志,显示由近及远的提交日志信息
  • git reset --hard HEAD^
    • 这里的HEAD^是回退到上一个版本,多个版本的话就是多个^ ,即 HEAD^^,
    • 或者HEAD~number,指定回退多少个版本
    • 或者使用具体的版本提交名,代替HEAD^,回退到指定版本
  • 演示
    1. 使用 git log 查看提交日志
    2. 使用 git reset --hard HEAD^ 回退到上个版本
    3. 使用 git log 查看当前提交日志,此时只会显示回退到的当前版本之前的提交信息
    4. 如果想再次回到最初的版本怎么做呢?找到当初版本提交的 commitId,使用 commitId进行制定版本回退
    5. 如果找不到commitId呢?使用 git reflog命令,查看每一次操作的命令,即可找到当时操作的commitId,通过commitId即可回退到任意版本
    6. 注意:commitId就是每次提交的时候的一连串字符加数字组成的字符串,在使用commitId进行回退的时候,只需要指定前几位即可找到对应版本

  • 小结
    • 使用git log可以查看提交历史,以确定要回退的版本
    • 使用 git reset --hard HEAD^可以跳转到之前版本
    • 使用 git reset --hard commitId 可以跳转到指定版本
    • 使用 git reflog 查看命令历史,用来确定要回退的版本

4.3 工作区和暂存区

  • 工作区:工作区就是在电脑里面能看到的目录
  • 版本库:工作区有一个隐藏目录.git,即版本库
    • 版本库里面有很多东西,其中最重要的就是如下三个
    • stage:暂存区
    • master:git为我们自动创建的第一个分支
    • HEAD:指向master的指针

通常情况下,我们往Git版本库里面提交代码的时候,是分两步执行的

  1. 使用 git add 把文件添加进去,实际上就是将文件添加到暂存区
  2. 使用 git commit 提交更改,实际上就是把当前暂存区的所有文件提交到当前分支上去
  3. 可以简单的理解为,需要提交的文件通过 git add 统统放到暂存区,然后,通过git commit一次性提交暂存区的所有修改

演示:

  1. 使用vi 文件名命令随意修改readme.txt文件一些内容

  2. 使用 vi lisense 新建lisense文件并且随意添加一些内容

  3. 使用git status查看当前工作区状态

    • git告诉我们readme.txt被修改了,而lisense还没有被添加过,所以状态是 untracked
    $ 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.txt
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
    	LICENSE
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
  4. 现在使用两次 git add 命令分别添加这两个文件到暂存区

    • 暂存区状态变为这样了

  5. 最后使用 git commit 命令将暂存区内容提交到master分支

拓展:

  • 使用 git diff 查看工作区和暂存区代码的区别
  • 使用 git diff --cached 查看暂存区和master分支的区别
  • 使用 git diff HEAD -- 文件名 可以查看工作区和版本库里面最新版本的区别

4.4 撤销修改

  • git checkout -- 文件名:将文件在工作区的修改全部撤销
    1. 文件修改之后还没有放到缓存区,撤销修改就会回到和版本库一模一样的状态
    2. 文件修改之后已经添加到暂存区,又做了修改,这时候撤销回到添加到暂存区之后的状态
  • git reset HEAD 文件名:将文件在暂存区的修改全部撤销

演示:撤销工作区

/**
 * 1. 修改文件 readme.txt
 * 2. 查看工作区状态
 * 3. 撤销readme.txt文件的修改
 * 4. 查看工作区状态
*/

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ vi readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ 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.txt

no changes added to commit (use "git add" and/or "git commit -a")

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git checkout -- readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git status
On branch master
nothing to commit, working tree clean

撤销暂存区的修改

/**
 * 1. 修改文件 readme.txt
 * 2. 提交到暂存区
 * 3. 查看工作区状态
 * 4. 撤销暂存区修改
 * 5. 查看工作区状态
*/
admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ vi readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git add readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt


admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git reset HEAD readme.txt
Unstaged changes after reset:
M       readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ 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.txt

no changes added to commit (use "git add" and/or "git commit -a")

4.5 删除文件

  • git rm 文件名:删除文件
    • 删除文件之后,要提交到分支上
  • 错误的删除了文件
    • 使用 git checkout -- 文件名,撤销工作区的修改
  • 注意:撤销后,会丢失最后一次提交后的修改

5. 远程仓库

5.1 创建远程仓库

  1. github上新建一个空的远程仓库
  2. 关联本地仓库
  3. 将本地仓库的内容提交到远程库上
//关联本地仓库
git remote add origin git@server-name:path/repo-name.git

git push -u origin master

//后续提交使用如下命令即可
git push origin master

注意:第一次提交的到远程仓库的时候,使用 git push -u origin master

5.2 从远程仓库克隆

  • 要克隆一个仓库,必须先知道仓库的地址,然后使用git clone命令克隆
  • git支持多种协议,包括 https,但是通过ssh支持原生的git协议速度是最快的
$ git clone git@github.com:mapengfei47/learnGit.git
Cloning into 'learnGit'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 9 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.

6. 分支管理

6.1 创建和合并分支

  • git branch:查看当前分支
  • git branch name:创建分支
  • git checkout name:切换分支
  • git checkout -b name:创建加切换分支
  • git merge name:合并某分支到当前分支
  • git branch -d name:删除分支

分支合并图解

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点

每次提交,master分支都会向前移动一步。这样,随着你不断提交,master分支就会越来越长

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

演示:

//查看当前分支
admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git branch
* master

//创建并且切换到dev分支
admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git checkout -b dev
Switched to a new branch 'dev'

//查看当前分支
admin@mapengfei MINGW64 ~/desktop/learnGit (dev)
$ git branch
* dev
  master
  
//修改文件
admin@mapengfei MINGW64 ~/desktop/learnGit (dev)
$ vi readme.txt

//将文件提交到dev分支
admin@mapengfei MINGW64 ~/desktop/learnGit (dev)
$ git add readme.txt

admin@mapengfei MINGW64 ~/desktop/learnGit (dev)
$ git commit -m "add something to dev"
[dev 23ade2d] add something to dev
 1 file changed, 1 insertion(+)
                             
//切换到master分支
admin@mapengfei MINGW64 ~/desktop/learnGit (dev)
$ git checkout master
Switched to branch 'master'

//将dev分支合并到master分支
admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git merge dev
Updating 5f57887..23ade2d
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
                             
//删除dev分支
admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git branch -d dev
Deleted branch dev (was 23ade2d).

admin@mapengfei MINGW64 ~/desktop/learnGit (master)
$ git branch
* master

6.2 解决冲突

  • 在进行git操作的时候,我们难免会做出如下的操作

新建一个分支,修改文件,提交文件

切换回master分支,修改master分支的文件,提交文件

合并分支

此时,分支的流程图是这样的

这种情况下,git无法执行分支的合并,会产生冲突

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

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

解决方法

  1. 使用 cat 冲突的文件名 查看冲突的文件

    • Git用<<<<<<<=======>>>>>>>标记出不同分支的内容,
    $ cat readme.txt
    add a file
    <<<<<<< HEAD
    this is master;
    add something
    =======
    add dev test;
    >>>>>>> dev
    
  2. 使用 vi 文件名 命令修改冲突文件,重新提交即可

  3. 现在分支变成了这样,删除dev分支即可

7. TortoiseGit

TortoiseGit是一个Git版本控制客户端

具体安装使用不做具体讲解,网上写的好的博客比较多

TortoiseGit的本地使用(图文详细介绍)

二. Git使用技巧整理

1. 给文件重命名的简便方法

  • 一般情况下,我们要修改文件名,需要依次执行如下步骤

    1. 在工作区将文件重命名
    mv 旧文件名 新文件名
    
    1. 将新文件添加到暂存区
    git add 新文件名
    
    1. 删除旧文件
    git rm 旧文件名
    
    1. 提交到git仓库
    git commit -m 'update readme.txt to readme.md'
    
  • 简便方法

    • 直接使用 git mv 旧文件名 新文件名
    git mv readme.txt readme.md
    git commit -m 'update readme.txt to readme.md'
    

2. 使用GIt自带图形化界面查看版本提交历史

在项目目录下打开命令行,输入 gitk 即可弹出Git自带图形化界面

3. .git目录介绍

重点了解如下几个文件:

  1. HEAD文件:

    • 指向当前分支
    • 可通过 cat HEAD 命令查看HEAD文件的内容,内容就是对当前分支的指向,如下 master就是当前分支
    • 可直接修改HEAD文件内容修改当前分支的指向,也可以再命令行通过 git checkout 分支名 来修改,两边内容会同步

  2. refs

    • refs包含两个文件夹,heads 和 tags

    • heads里面包含所有的分支信息,通过查看heads里面的分支信息,可以找到当前分支对应的Hash值

    • tags里面包含所有的tag信息

  1. objects

    • objects文件目录下面包含很多个文件夹,详情见如下操作

4. Git里面的几种文件类型

通过Hash值查看文件类型和文件内容的命令

  • git cat-file -t 文件的hash值 :查看对应Hash值文件的文件类型
  • git cat-file -p 能确定文件的Hash名 :查看对应Hash值文件的文件内容

提示:

  • 实际调试过程中,可通过 git log 命令查看所有commit,然后通过上面介绍的命令,查看对应commit Hash对应的类型,逐层递进,查看 tree,blob

Git里面包含如下几种文件类型

  1. commit:每次使用 git commit 命令都会生成一个 commit 对象。可以想象为每一个commit的顶层文件目录对象
  2. tree:每一个commit都有一个唯一的 tree。tree可以想象为文件夹
  3. blob:最小单位,每一个blog对应一个文件
    • 注意:git会将内容相同的多个文件存储为一个具有唯一Hash值的单个文件

解构图示: