zl程序教程

您现在的位置是:首页 >  其他

当前栏目

深入Git —— 从底层对象到常用命令速刷手册

2023-02-18 16:23:07 时间

首先来简单介绍下Git,Git是一款分布式版本控制工具,需要存储大量的文件内容数据,其中Git objects发挥了关键的作用。Git objects基本存储了Git的一切,多种类型的对象和对象之间的引用共同构成了Git版本控制的核心。

Git objects的存储特点如下:

  • Git Objects会松散存储在仓库的.git/objects/目录下
  • Git Objects采用key-value的形式进行存储
  • 不同的Object,Git会为其生成唯一的key
  • key的格式是SHA1形式(表现为40位的16进制字符串)或者SHA-256

Git Objects包含了4种类型,其中:

  • Blob对象用于存储文件内容;
  • Tree对象用于进行目录索引,它保存了某个目录下的一个完整视图;
  • Commit对象负责存储提交的元数据(作者、说明、父提交等),同时还引用一个根目录的索引视图;
  • Tag对象一般用于标记发行版等提交时刻及相关信息。

这里通过一个简单实例做个演示,首先通过git init test 初始化一个仓库并进入仓库中,创建一个README.md文件,然后执行git add README.md添加到暂存区,再用git commit -s 提交代码,在test下新建src和docs目录存放代码main.c和文档project.txt,再将src和docs使用git add和git commit完成提交,最后执行git tag -a -m "Release V1.0" v1.0 记录tag为1.0版本。我们分别将两次提交作为commitA 和 commitB,那么两次提交中Git Objects的组织关系如下图:

我们刚刚提到Git对象是用SHA1或者SHA-256格式存储,由于其表现形式不方便使用,所以需要用到Git 引用。它通常存储在仓库的.git/refs/目录下,Git支持4种默认的Builtin reference:

  1. Branches:分支的引用。存储位置:.git/refs/heads/<branch>
  2. Tags:标签的引用。存储位置:.git/refs/tags/<tag>
  3. Remotes:与远端协作时使用。存储位置:.git/refs/remotes
  4. Symbolic:符号引用 HEAD。存储位置:.git

这里的符号引用,即为指向引用的引用,HEAD是一种特殊的符号引用,它指向你当前所在分支的引用,你可以通过git symbolic-ref HEAD来查看符号引用 HEAD的相关信息。


底层内容能够更好的帮助我们了解一款软件,下面阿巩尽量白话介绍基础并引入常用命令。

01 创建仓库

“仓库”是指与项目相关的所有文件,包括源代码、工程文件、资源文件和一些配置信息,它可以是本地的仓库,也可以是保存在远端服务器上的仓库。仓库之间可以相互同步,你可以把本地代码同步到远程服务器上。

获取本地Git仓库:

进入目录:$ cd /Users/user/my_project
初始化git仓库:$ git init
创建一个名为 .git 的子目录
跟踪项目文件:$ git add .
初始提交git仓库:$ git commit -m 'initial project version'

从远端服务器获取已存在的Git仓库:

$ git clone https://github.com/libgit2/libgit2
自定义本地仓库的名字:
$ git clone https://github.com/libgit2/libgit2 mylibgit

02 更新仓库

检查当前文件状态:

$ git status
$ git status -s(简洁输出)
    ?? 未跟踪的文件
    A 新添加到暂存区
    M 修改过的文件

查看具体哪些行发生变化

查看尚未暂存的文件:
$ git diff
查看已暂存的将要添加到下次提交里的内容:
$ git diff --staged

提交更新

提交暂存区:
$ git commit
命令+消息:$ git commit -m "...“
不使用暂存区:
$ git commit -a -m “...”  不需要git add步骤

如果想更改一次提交

$ git commit --amend

从暂存区移除文件

未暂存清单中删除
$ git rm
暂存区移除
$ git rm --cached README
    文件保留在磁盘,但是并不想让 Git 继续跟踪

移动文件

$ git mv file_from file_to

查看提交历史

$ git log

撤销操作

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终你只会有一个提交——第二次提交将代替第一次提交的结果。
撤消对文件的修改:
  放弃修改: $ git checkout -- <file>...
    Git 会用最近提交的版本覆盖掉

取消暂存的文件

$ git reset HEAD <file>...

也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。

使用远程仓库

git clone 默认设置本地 master 分支跟踪克隆的远程仓库的 master 分支

$ git clone https://github.com/schacon/ticgit

查看使用的远程仓库

$ git remote -v

添加远程仓库

$ git remote add pb https://github.com/paulboone/ticgit
  使用字符串 pb 来代替整个 URL

拉取远程仓库有但本地没有的信息

$ git fetch <remote>
   只下载数据到本地仓库,需要另外进行合并

配置了跟踪远程分支

自动抓取后台合并到当前分支:$ git pull

推送到远程仓库

$ git push origin master

查看某个远程仓库

$ git remote show origin

打标签记录发布节点 v1.0 、 v2.0 等等)

列出标签
  $ git tag
  $ git tag -l "v1.8.5*"
创建标签
  保存版本信息—————附注标签
      $ git tag -a v1.4 -m "my version 1.4"
        带-a,-m为添加到标签内的信息
  不保存,只用作标识—————轻量标签
      $ git tag v1.4-lw
        直接提供标签名即可
查看标签
  $ git show v1.4-lw
后期打标签
  查看提交历史
    $ git log --pretty=oneline
  在指定版本上打标签
    $ git tag -a v1.2 9fceb02
由于git push 命令并不会传送标签到远程仓库服务器上需要额外推送标签
  $ git push origin v1.5
  $ git push origin --tags 批量推送
删除标签
  $ git push origin --delete <tagname>

Git分支

在进行提交操作时,Git会保存一个提交对象,该提交对象会包含一个指向暂存内容快照及作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。

分支创建

$ git branch testing  在当前所在的提交对象上创建一个指针
查看各个分支当前所指的对象
  $ git log --oneline --decorate

分支切换

$ git checkout testing
$ git checkout master
  1、使 HEAD 指回 master 分支
  2、恢复master 分支所指向的快照

分支的新建与合并流程

  1、新建并切换
    $ git checkout -b hotfix
  2、提交修改
    $ git commit -a -m 'fixed the broken email address'
  3、切换到master分支
    $ git checkout master
  4、将hotfix合并回master分支部署到线上
    $ git merge hotfix
  5、删除hotfix分区继续在自己的分支工作
    删分支:$ git branch -d hotfix
    切回分支:$ git checkout iss53
    提交修改:$ git commit -a -m 'finished the new footer [issue 53]'

查看分支信息

查看分支
  $ git branch
    分支前的 * 字符:它代表现在检出的那一个分支
查看每一个分支的最后一次提交
  $ git branch -v
查看哪些分支已经合并到当前分支
  $ git branch --merged
查看所有包含未合并工作的分支
  $ git branch --no-merged

远程分支操作

推送
  $ git push <remote> <branch>
  $ git push origin serverfix:awesomebranch 来将本地的 serverfix 分支推送到远程仓库上的 awesomebranch 分支。
拉取
  $ git fetch origin
合并
  $ git merge origin/serverfix
建立跟踪
  $ git checkout -b serverfix origin/serverfix
  如果检查的分支不存在,使用快捷方式跟踪
    $ git checkout --track origin/serverfix
删除远程分支
  $ git push origin --delete serverfix
    只删除指针,可恢复

变基

变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上
  $ git rebase --onto master server client
    “取出 client 分支,找出它从 server 分支分歧之后的补丁, 然后把这些补丁在 master 分支上重放一遍,让 client 看起来像直接基于 master 修改一样”
  $ git checkout master
$ git merge client
  $ git rebase master server
  $ git checkout master
$ git merge server
  $ git branch -d client
$ git branch -d server

五种提高代码提交原子性的基本操作

1、把工作区里代码改动的一部分转变为提交

$ git add -p
$ git diff --cached 命令检查

2、对当前提交进行拆分

当前提交,指的是当前分支的 HEAD 指向的提交。

1、git log 查看历史
2、git show 确认提交内容改动
3、git branch temp 命令产生一个临时分支 temp,指向当前 HEAD
  便于恢复
    git reset --hard temp
4、git reset HEAD^ 命令
  当前分支指向目标提交 HEAD^
5、git add -p分块提交

3、修改当前提交

修改conmmit message
  git commit --amend 命令
修改的是文件内容
  1、使用 git add、git rm 等命令把改动添加到暂存区
  2、git commit --amend修改信息
  3、输入 Commit Message 保存退出即可

4、交换多个提交的先后顺序

1、git branch temp 产生一个临时分支
2、git log --oneline --graph 来确认当前提交历史
3、git rebase -i origin/master
4、使用pick命令把A、B重新放到origin/master上
pick 7b6ea30 Add a new endpoint to return timestamp
pick b517154 Change magic port number to variable

5、修改非当前提交

1、运行 git rebase -i origin/master
2、把原来的“pick b517154”的一行改为“edit b517154”(b517154 是提交 A 的 SHA1)
  告知 Git rebase 命令,在应用了 b517154 之后,暂停后续的 rebase 操作,
  直到我手动运行 git rebase --continue 通知它继续运行
3、git log --oneline --graph --all,确认当前 HEAD 已经指向了我想要修改的提交 A。
4、修改文件,之后用 git add < 文件名 >,然后再运行 git commit --amend。
5、git rebase --continue,完成 git rebase -i 的后续操作
  在 A 之上再应用提交 B,并把 HEAD 重新指向了 B,从而完成了对历史提交 A 的修改。

多分支工作流具体步骤

假设现在有这样一个业务场景:我首先开发需求 C,并把它的提交 C1 发送到质量检查中心;然后开始开发需求 D,等到 C1 通过质量检查之后,我立即将其推送到远程共享代码仓中去。

这个流程分为以下四个阶段:

  • 阶段 1:开发需求 C

使用 git checkout -b feature-c origin/master 产生本地分支 feature-c,并跟踪 origin/master,然后进行 C 的开发,产生提交 C1。

  • 阶段 2:开发需求 D

使用 git checkout -b feature-d origin/master 产生一个分支 feature-d 并跟踪 origin/master,然后进行 D的开发,产生提交 D1。

  • 阶段 3:推送提交 C1 到远端代码仓共享分支

使用git checkout feature-c 把分支切换回分支 feature-c,执行git fetch和git rebase origin/master来确保我的分支上有最新的远程共享分支代码;然后执行git push推送 C1。

  • 阶段 4:继续开发 D1

执行git checkout feature-d 把分支切换分支 feature-d,执行git fetch和git rebase origin/master,使用git log --oneline --graph feature-c feature-d来查看提交状态。

参考:

https://git-scm.com/

极客时间《研发效率破局之道》

阿里云《Git教程》

中秋快乐