Git——再不会就out了

1. Git 初始化配置

查看git版本:git --version

配置信息:

git config --global user.name "ice"
git config --global user.email "ice@example.com"

这样你提交代码有bug时,测试人员可以查到是谁提交,并向你发邮件

这里可以设置几个级别的配置:

  • --system:针对当前系统的配置
  • --global:针对当前用户的配置
  • 不写参数:默认只针对此项目配置

要查看已有的配置信息,可以使用命令:

git config --list

2. Git 底层命令

2.1 基础的 Linux 命令

  • clear:清屏

  • echo:往控制台打印信息,如:
    在这里插入图片描述

  • ls系列命令(简略):

    • ls -1
      每行仅显示一个文件或目录名称
      在这里插入图片描述
    • ls -als --all
      列出当前目录下下所有文件和目录
      在这里插入图片描述
    • ls -Als --almost-all
      类似ls -a,但是不列出当前目录和父目录
      在这里插入图片描述
    • llls -l
      显示当前目录下文件详细信息
      在这里插入图片描述
  • find 目录名

    将对应目录下的所有文件&子孙目录显示到控制台
    在这里插入图片描述

  • find 目录名 -type f
    将对应目录下的所有文件显示到控制台
    在这里插入图片描述

  • rm 文件名
    删除文件

  • mv src dest
    移动文件,可以用此命令重命名文件

  • cat 文件url
    查看对应文件内容

  • vim 文件url
    i进入插入模式,进行文件得编辑
    编辑完成后,先按ESC,然后输入:进行命令的执行

    • q!:强制退出,不保存
    • wq:保存退出
    • set nu:设置行号

2.2 初始化新仓库

命令:

git init

在你工作区文件夹内执行,将其纳入Git管理

创建完成后,该文件夹里会创建一个.git文件夹,里面包括:

在这里插入图片描述
其中每个文件夹含义为:

  • hooks:该目录包含客户端或服务端的钩子脚本,类似面向切面编程
  • info:该目录包含一个全局性排除文件
  • logs:该目录保存日志信息
  • objects:该目录存储所有的数据内容
  • refs:该目录存储指向数据(分支)的提交对象的指针
  • config:该文件包含项目特有的配置选项
  • description:该文件用来显示对仓库的描述信息
  • HEAD:该文件指向目前被检出的分支
  • index:该文件保存暂存区信息

2.3 git 对象

Git 的核心部分是一个简单的键值对数据库。你可以向数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索该内容。

  • 向数据库写入内容,并返回对应键值
    例如:

    echo 'hello world' | git hash-object -w --stdin
    

    -w选项指示hash-object命令存储数据对象;若不指定此选项,则该命令仅反回对应的键值

    --stdin选项则指示该命令从标准输入读取内容;若不指定此选项,则须在该命令尾部给出待存储文件得路径

  • 根据键值拉取数据

    git cat-file -p 哈希值
    

    -p选项指示该命令自动判断内容的类型,并为我们显示格式友好的内容

    返回对应文件得内容

在这里插入图片描述

  • 对一个文件进行简单的版本控制

    • 将一个文件纳入Git数据库

      git hash-object -w ./text.txt
      
    • 查看存储的内容

      git cat-file -p 04be3f68d453d5754167c0e0cbcd91c92d61bf39
      

    在这里插入图片描述

    在这里插入图片描述

    修改文件后阻碍次提交,会生成2个hash,并不是增量提交

  • 问题

    • 记住文件的每一个版本所对应的 SHA-1 值并不现实
    • 在 Git 中,文件名并没有被保存,我们仅保存了文件得内容

    解决方案:树对象

2.4 树对象

树对象,它能解决文件名保存的问题,也允许我们将多个文件组织到一起。Git 以一种类似于UNIX 文件系统的方式存储内容。所有内容均以树对象和数据对象(git对象)的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象(git对象)则大致上对应文件内容。一个树对象包含了一条或多条记录(每条记录含有一个指向git对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息)。一个树对象也可以包含另一个树对象。

  • 查看暂存区

    git ls-files -s
    
  • 构建树对象
    我们可以通过 update-indexwrite-treeread-tree等命令来构建树对象并塞入到暂存区

    • 利用update-index命令为 text.txt 文件首个版本创建一个暂存区,并通过write-tree命令生成树对象

      git update-index --add --cacheinfo 100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt
      

      文件模式:

      • 100644:表示一个普通文件
      • 100755,:表示一个可执行文件
      • 120000:表示一个符号链接

      --add选项:因为此前改该文件并不在暂存区中,首次需要使用此选项添加

      --cacheinfo选项:因为要添加的文件位于 git 数据库中,而不是位于当前目录下,所以需要此命令

      此时暂存区就有内容了
      在这里插入图片描述

      • 从上面结果可以看出,git对象和树对象都是存储在objects文件夹内的
      • update-index命令是创建缓存区,write-tree是将暂存区生成树对象,存入版本库(数据区)
      • write-tree写入版本库时不会删除暂存区内容

      git对象代表文件的一次次版本,树对象代表项目的一次次版本

    • 新增 new.txt 将 new.txt 和 test.txt 文件得第二个版本塞入暂存区,并通过write-tree 命令生成树对象存入版本库
      在这里插入图片描述

      这里可以看出,修改过的文件和修改前的文件存的是2个git对象,hash值是不同的


      在这里插入图片描述

      git update-index --add new.txt这个命令会执行2个操作,先是创建git对象存储到版本库,紧接着创建树对象到暂存区


      在这里插入图片描述

    • 将第一个树对象加入第二个树对象,使其成为新的树对象
      在这里插入图片描述

      此时项目的第三个版本不仅包括修改过的 test.txt 和 new.txt,还包括最初的 test.txt 版本

  • 问题
    现在有的三个树对象,分别代表了我们想要跟踪的不同项目快照。然而问题依旧:若想重用这些快照,你必须记住所有三个 SHA-1 哈希值;并且,你也完全不知道是谁保存了这些快照,在什么时候保存的,以及为什么保存这些快照。而以上这些,正是提交对象能为你保存的基本信息。

2.5 提交对象

我们可以通过调用 commit-tree 命令创建一个提交对象,为此需要指定一个树对象的 SHA-1 值,以及该提交的父提交对象(如果有的话,第一次将暂存区做快照就没有父对象)

  • 样例一

在这里插入图片描述

  • 样例二

在这里插入图片描述

-p后面跟的是前一个的提交对象的 SHA-1

真正代表一个项目版本的就是提交对象,它是对树对象的封装。

3. Git 操作最基本流程

  1. 创建工作目录,初始化新仓库,git init
  2. 将修改的文件提交到暂存区,git add ./
  3. 将暂存区内容提交,git commit -m "注释"

git add命令是先把文件生成为git对象存储到版本库,再将其快照添加到暂存区

git commit命令是先根据暂存区内容生成一个树对象,存储到版本库,然后再将其拿出来包裹成提交对象,再出存储到版本库

commit 后暂存区内容仍然存在

4. Git 其他常用高级命令

4.1 检查当前文件状态

git status

一般来说,所有文件不外乎两种状态:已跟踪未跟踪

已跟踪的状态可能是已修改已提交已暂存

4.2 查看已暂存和未暂存的更新

实际上git status显示的比较简单,仅仅是列出了修改过的文件,如果要查看具体修改了什么地方,可以用git diff命令。这个命令它已经能解决我们两个问题了:当前做的哪些更新没有被暂存?有哪些更新已经暂存起来准备下次提交?

  • 当前做的哪些更新还没有暂存

    git diff
    
  • 有哪些更新已经暂存起来准备下次提交

    git diff --cached
    
    git diff --staged  // 1.6.1及以上
    

4.3 提交

之前提到的提交命令git commit -m "注释"适合注释短的适合,要是注释很长可以直接执行命令

git commit

然后进入vim编辑模式,写大段注释。

4.4 跳过使用暂存区提交

尽管使用暂存区的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。Git提供了一个跳过使用暂存区的方式,只要在提交的时候,给git commit加上-a选项,Git就会自动把所有已经跟踪过的文件暂存起来一起提交,从而跳过git add步骤,即git commit -a

4.5 移除文件

删除文件在Git中被视为修改操作,可以使用git rm命令完成此操作,并连带从工作区删除实体文件,此操作不会生成新的git对象,但是提交同样会产生树对象和提交对象

4.6 文件改名

如果直接用mv命令改名,其实是先删除一个文件,在新增一个文件,git中有命令git mv可以直接完成此操作。

注意本质是删除和新增文件

4.7 查看历史记录

  • git log
    在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。完成这个任务最简单有效的工具是git log命令
    在这里插入图片描述
    默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的提交在最上面。

    该命令会列出每个提交的 SHA-1 值、作者的名字和邮箱、提交时间以及提交说明

  • git log 参数

    • git log --pretty=oneline
      在这里插入图片描述
    • git log --oneline
      在这里插入图片描述

4.8 Rebase

一般只在本地分支用!不要轻易用于远程仓库!

4.8.1 修改老旧的commit message

提交历史如下所示:

在这里插入图片描述

例如将v2 的commit message 修改成v2.1

执行命令git rebase -i <commithash>

-i表示交互式

commithash应该是要修改的提交的前一次提交(parent),这里是v1commithash

执行git rebase -i 516bbaaca100da099ecd4ff27528822db5896d10后界面如图:

在这里插入图片描述

作如下修改:

在这里插入图片描述

其实这里面是编辑命令,编辑完git会自动执行

这里保存退出会进入另一个交互式的vim编辑窗口:

在这里插入图片描述

修改commit message保存退出即可:

在这里插入图片描述

此时界面会显示修改成功,现在看看提交历史:

在这里插入图片描述

已经修改完成

4.8.2 合并多个连续commit

这个现象很常见,一开始开发很容易完成一部分就像提交一次保存,但是对于整个项目来说,这种太密集了,没有意义,只需对一个功能保留一个提交即可,所以需要合并多个commit,一般情况下这些commit都是连续的。

在这里插入图片描述

初始log记录如上面图片所示,想要合并提交还是需要使用Rebase命令,比如合并v2v4,命令中的commithash应为v1的:

git rebase -i d8081efefc598caeb05f00b13e08d52bdef3a112

在这里插入图片描述

这里选择squash命令,保存退出后,进入下一个vim编辑界面,这个就是合成后的commit message编辑界面:

在这里插入图片描述

保存退出:

在这里插入图片描述

此时在查看提交日志:

在这里插入图片描述

4.8.3 合并几个间隔的commit

下面介绍如果一个功能的commit不是连续的如何解决合并问题,初始提交记录如下所示:

在这里插入图片描述

现在想把create a.txtcreate c.txt合并起来,由于create a.txt已经是最早的提交了,没有parent,故只能执行:

git rebase -i 64231128d6df0b6

进入该commit 然后vim编辑器中手动添加它,才进入是这样的:

在这里插入图片描述

你我们需要修改成这样:

在这里插入图片描述

保存退出后,返回git bash并现实一些信息,继续执行命令:

git rebase --continue

进入如下vim编辑界面:

在这里插入图片描述

此时可以修改合并后的提交message,如改成这样:

在这里插入图片描述

保存退出后,显示成功修改:

在这里插入图片描述

此时查看提交历史:

在这里插入图片描述

5. Git 分支操作(杀手功能)

几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费许多时间。而 Git 的分支模型是极其搞高效轻量的,是 Git的必杀技特性,也正是因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。

分支就是指向一个提交对象的活动的指针

5.1 创建分支

git branch 分支名

创建一个新分支,但是并不会自动切换到新分支中去

在这里插入图片描述

如果你想直接切换到新建的分支,可以执行下面命令

git checkout -b 分支名

5.2 查看当前所有分支的列表

git branch

在这里插入图片描述

5.3 切换分支

git checkout 分支名

在这里插入图片描述

切换分支会动三个地方:

  • HEAD
  • 暂存区
  • 工作目录

【最佳实践】每次切换分支前,当前分支一定是干净的(已提交状态)

5.4 查看项目分支历史

git log --oneline --decorate --graph --all

可以看到类似下面的结果:

在这里插入图片描述

5.5 合并分支

git merge 分支名

执行此命令是将其它分支合并到当前执行命令时所在的分支

有时候合并分支会有冲突,只要解决文件的冲突提交即可

5.6 删除分支

【注】不能删除当前所在分支,需要先切出去再删除

git branch -d 分支名
git branch -D 分支名

区别在于-d会检查merge状态,分支没有合并会报错,-D则会强制删除

5.7 查看每个分支的最新提交

git branch -v

在这里插入图片描述

5.8 创建一个指向特定提交对象的分支

git branch 分支名 提交对象的hash值

想回哪里回哪里,就是版本回退

5.9 查看哪些分支已合并到当前分支

git branch --merged

在这个列表中分支名前没有*号的分支通常可以使用git branch -d删除掉

5.10 查看哪些分支未合并到当前分支

git branch --no-merged

尝试使用git branch -d命令删除在这个列表中的分支时会失败

5.11 分支模式

一般项目都有个主分支,一般不直接在上面进行开发,每个程序员都需要自己在此基础上拉一个自己的分支来开发,一般以自己花名来为开发分支命名。

具体开发每一个功能时,其实最好还是在自己的开发分支上再拉一个分支,开发完了再合并到自己的分支上,所以功能开发测试完毕再合并到主分支中。

5.12 分支原理

  • .git/refs 目录

这个目录中有两个文件夹,heads 和 tags,分别存储分支和标签及其所对应的提交对象的hash值。

在这里插入图片描述

  • HEAD 引用

当运行类似于git branch branchname这样的命令时,Git 会取得当前所在分支最新提交对应的 SHA-1 值,并将其加入到你想要创建的任何新分支中。那么,如何知道 SHA-1 值呢,答案是通过 HEAD 文件。

HEAD 文件是一个符号引用,指向目前所在分支。所谓符号引用,意味着它并不像普通引用那样包含一个 SHA-1 值,他是一个指向其他引用的指针。

6. 别名

6.1 新建别名

Git 不会在你输入部分命令时自动推断出你想要的命令。如果不想每次输入完整的 Git 命令,可以给这些命令设置别名。

git config --global alias.别名 原命令

一般用--global够了,因为主要就是为用户自定义快捷命令设置别名的

原命令不包过第一个单词git,如果超出一个单词需要给命令整体加引号

在这里插入图片描述

6.2 删除指定别名

git config --global --unset alias.别名

在这里插入图片描述

6.3 删除所有别名

git config --global --remove-section alias

7. Git 存储

有时,当你在开发分支上工作一段时间临时要切换到另一个分支做点事,可你又不想就此提交,此时你需要用到git stash命令。

  • git stash
    将未完成的修改保存到一个栈上,而你可以在任何时候重新应用这些改动。

  • git stash list
    查看存储
    在这里插入图片描述

  • git stash apply stash@{0}
    注意stash@{0}是根据存储列表得到的标识符,如果不指定一个存储,调用命令git stash apply,则默认是最近的一个存储

  • git stash pop
    应用存储,然后立即从栈上扔掉它

  • git stash drop 存储名
    移除指定存储

8. 撤销 & 重置

8.1 撤回在工作区的修改

git restore <filename>

在这里插入图片描述

此命令针对的是已经被追踪的文件,之后有过修改,但是还没有执行git add之前,要是想反悔,可以使用这个命令回退到修改前。

8.2 撤回暂存区的快照

git restore --staged <filename>

在这里插入图片描述

此命令针对的是已经执行git add命令,但是还没有git commit,要是想反悔,可以使用这个命令回退到git add前。

8.3 撤回自己的提交

  • 提交注释写错了

    比如执行git commit -m "提交注释",提交完发现有问题,需要重写,可以先修改发现错误的文件,然后执行git commit --amend进入VIM模式创新编辑注释,之后 Git 会自动提交。

    在这里插入图片描述

  • 已经提交了不合适的修改到版本库时,想要撤销本次提交
    版本回退,前提是你没有推送到远程版本库

9. 版本回退

9.1 soft

git reset --soft HEAD~

这与改变 HEAD 自身不同,reset 移动 HEAD 指向的分支,意思就是,不简单是 HEAD 指向前面某个版本,而是 HEAD 还是指向当前分支,但是当前分支指向的版本变了。

HEAD后面几个~,就回退几个版本

它本质上是撤销了上一次git commit命令。当你运行git commit时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交。

暂存区并没有变化

git reset --soft HEAD~=git commit --amend

9.2 mixed

git reset [--mixed] HEAD~

不仅移动 HEAD(带着分支一起移动),还改变了暂存区

9.3 hard

git reset --hard HEAD~

mixed基础上,还改变了工作区

这是一个危险用法,它是 Git 会真正销毁数据的仅有的几个操作之一

git checkout 分支名git reset --ghard XXX区别:

  • git checkout只动 HEAD,--hard动HEAD而且带着分支一起走
  • git checkout对工作目录是安全的,--hard强制覆盖工作目录

10. 标签

Git 可以给历史中的某一个提价打上标签,以示重要,比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 等等)

10.1 列出标签

git tag

10.2 创建标签

Git 使用两种主要类型的标签:轻量标签和附注标签

  • 轻量标签很像一个不会改变的分支——它只是一个特定提交的引用
    git tag v1.0或者git tag v1.0 commithash指定某个版本打标签

  • 附注标签是存储在 Git 数据库中的一个完整对象。它们是可以被校验的,其中包含打标签者的名字、email地址、日期时间,还有一个标签信息。通常建议创建附注标签,这样你可以拥有以上所有信息。但如果你只是想用一个临时的标签,或者因为某些原因不想保存那些信息,轻量标签也是可用的。

    git tag -a v1.1
    git tag -a v1.2 commithash
    git tag -a v1.3 commithash -m "my version v1.3"
    

10.3 查看特定标签

git show tagname

10.4 删除标签

git tag -d tagname

10.5 检出标签

如果你想查看某个标签所指向的文件版本,,可以使用git checkout tagname命令,但是会使仓库处于分离头指针(detached HEAD)状态。如果你此时做了某些修改想要提交,标签不会发生变化,但是新提交不属于任何分支,并且将无法访问,除非访问确切的提交hash值。因此,如果你需要进行更改——比如说你正在修复旧版本的错误,这通常需要创建一个新分支:

git checkout -b tagname

11. 远程协作流程

  1. 项目经理创建远程仓库
  2. 项目经理创建本地仓库
  3. 项目经理为远程仓库配置别名
    • git remote add <别名> <url>:添加远程仓库并设置别名
    • git remote -v:显示远程仓库使用的 Git 别名预期对应的url
    • git remote show <远程仓库别名>:查看某一个远程仓库更多信息
    • git remote rename <别名1> <别名2>:重命名
    • git remote rm <远程仓库别名>:删除远程仓库
  4. 项目经理推送本地项目到远程仓库
    git push <别名> <分支名>
  5. 成员克隆远程仓库到本地
    git clone <url>
  6. 项目成员邀请成员加入团队
  7. 成员推送提交到远程仓库
  8. 项目经理更新成员提交内容
    git pull

12. 远程分支

12.1 跟踪远程分支

本地创建新分支,推送到远程仓库时会自动添加新分支,但是此时之前克隆过仓库的成员再次通过git fetch命令下拉代码就需要可能先要创建一个分支来接受它(merge),然后可以执行下面命令来建立跟踪关系。

git branch -u <remotename>/<branch>
git checkout -b 本地分支名 <remotename>/<branch>
git checkout --track <remotename>/<branch>

都是新建分支,同时跟踪远程仓库的分支

命令git pull可以一次性将远程分支拉到本地分支上,省略了fetch后的merge过程,但是和上面一样,还是要先建立分支跟踪关系,这样pull的时候才会自动拉下来到对应分支上。

说白了,要想pull一步搞定,要确保每个分支已经和远程分支有跟踪关系了

12.2 删除远程分支

git push origin --delete <BranchName>  // 删除远程分支
git remote prune origin --dry-run      // 列出仍在远程跟踪,但是远程已被删除的无用分支
git remote prune origin                // 清除上面列出的远程分支

13. 远程冲突

每次写代码和提交代码前最好先git pull更新一下,有冲突先解决再提交,

14. 忽略文件

  • 格式规范
    • 所以空行或者以注释符号#开头的行都会被 Git 忽略
    • 可以使用标准的 glob 模式匹配
      • *代表匹配任意个字符
      • ?代表匹配任意一个字符
      • **代表匹配多级目录
    • 匹配模式前有/,表示根目录,比如/a表示仅忽略根目录下的a文件夹,其他路径下的a文件夹仍然保留
    • 匹配模式最后有斜杠,说明要忽略的是目录,比如b/,它表示忽略所有b文件夹,无论它在哪个层级
    • 前置!表示取反,不排除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值