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

首先来简单介绍下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 —— 从底层对象到常用命令速刷手册_第1张图片

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

  1. Branches:分支的引用。存储位置:.git/refs/heads/

  2. Tags:标签的引用。存储位置:.git/refs/tags/

  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 —— 从底层对象到常用命令速刷手册_第2张图片

提交更新​​​​​​​

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

深入Git —— 从底层对象到常用命令速刷手册_第3张图片

如果想更改一次提交

$ git commit --amend

深入Git —— 从底层对象到常用命令速刷手册_第4张图片

从暂存区移除文件​​​​​​​

未暂存清单中删除$ 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 -- ...    Git 会用最近提交的版本覆盖掉

    

取消暂存的文件

$ git reset HEAD ...

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

深入Git —— 从底层对象到常用命令速刷手册_第5张图片

图片

使用远程仓库

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    只下载数据到本地仓库,需要另外进行合并

配置了跟踪远程分支

自动抓取后台合并到当前分支:$ 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 

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 —— 从底层对象到常用命令速刷手册_第6张图片

查看分支信息​​​​​​​

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

远程分支操作 

推送  $ git push    $ 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

深入Git —— 从底层对象到常用命令速刷手册_第7张图片

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

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

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

2、对当前提交进行拆分

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

1、git log 查看历史2、git show 确认提交内容改动3、git branch temp 命令产生一个临时分支 temp,指向当前 HEAD  便于恢复    git reset --hard temp4、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/master4、使用pick命令把A、B重新放到origin/master上pick 7b6ea30 Add a new endpoint to return timestamppick b517154 Change magic port number to variable

5、修改非当前提交​​​​​​​

1、运行 git rebase -i origin/master2、把原来的“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来查看提交状态。

深入Git —— 从底层对象到常用命令速刷手册_第8张图片

 

欢迎你与我交流,催更扯淡一条龙~

 

参考:

https://git-scm.com/

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

阿里云《Git教程》

你可能感兴趣的:(git,git)