git食用指南 | 青训营

66 阅读14分钟

1 相关概念与快速开始

Git的安装与使用教程(超详细!!!)9.冄2.7.號的博客-CSDN博客git安装教程

版本控制是什么?

  • 一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统

为什么需要版本控制?

  • 更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生也能够随时切换到不同的版本,回滚误删误改的问题代码;

什么是 git

  • Git 是一款免费、开源的分布式版本控制系统,他是著名的 Linux 发明者 Linus Torvalds 开发的
  • GitHub 主要提供基于 git 的版本托管服务。也就是说现在 GitHub 上托管的所有项目代码都是基于 Git 来进行版本控制的,所以 Git 只是 GitHub 上用来管理项目的一个工具而已,GitHub 的功能可远不止于此!

1.1 GitHub 基本概念

Repository

  • 仓库的意思,即你的项目,你想在 GitHub 上开源一个项目,那就必须要新建一个 Repository,如果你开源的项目多了,你就拥有了多个 Repositories 。

Issue

  • 问题的意思,举个例子,就是你开源了一个项目,别人发现你的项目中有bug,或者哪些地方 做的不够好,他就可以给你提个 Issue ,即问题,提的问题多了,也就是 Issues ,然后你看 到了这些问题就可以去逐个修复,修复ok了就可以一个个的 Close 掉。

Star

  • 这个好理解,就是给项目点赞,但是在 GitHub 上的点赞远比微博、知乎点赞难的多,如果你有一个项目获得100个star都算很不容易了!

Fork

  • 这个不好翻译,如果实在要翻译我把他翻译成分叉,什么意思呢?你开源了一个项目,别人 想在你这个项目的基础上做些改进,然后应用到自己的项目中,这个时候他就可以 Fork 你的 项目,这个时候他的 GitHub 主页上就多了一个项目,只不过这个项目是基于你的项目基础 (本质上是在原有项目的基础上新建了一个分支,分支的概念后面会在讲解Git的时候说 到),他就可以随心所欲的去改进,但是丝毫不会影响原有项目的代码与结构。

Pull Request

  • 发起请求,这个其实是基于 Fork 的,还是上面那个例子,如果别人在你基础上做了改进,后 来觉得改进的很不错,应该要把这些改进让更多的人收益,于是就想把自己的改进合并到原 有项目里,这个时候他就可以发起一个 Pull Request(简称PR) ,原有项目创建人就可以收 到这个请求,这个时候他会仔细review你的代码,并且测试觉得OK了,就会接受你的PR,这 个时候你做的改进原有项目就会拥有了。

Watch

  • 这个也好理解就是观察,如果你 Watch 了某个项目,那么以后只要这个项目有任何更新,你 都会第一时间收到关于这个项目的通知提醒。

Gist

  • 有些时候你没有项目可以开源,只是单纯的想分享一些代码片段,那这个时候 Gist 就派上用 场了!

1.2 git 目录结构

  • Git 的本质是一个文件系统,工作目录中的所有文件的历史版本以及提交记录(commit)都是以文件对象的方式保存在 .git 目录中的。
  • git下的版本库只位于工作区根目录下的 git目录 , 仅此一处
  • 目前的Key的类型四种,分别是dsa、rsa、ecdsa、ed25519, 默认使用的是rsa, 由于一些安全问题,现在已经不推荐使用dsa和rsa了,优先推荐使用ed25519
├─hooks
├─info
├─logs
│  └─refs
│      ├─heads
│      └─remotes
│          └─origin
├─objects
│  ├─info
│  └─pack
└─refs
    ├─heads
    ├─remotes
    │  └─origin
    └─tags
  • objects:这里是真正保存 Git 对象的目录,包括三类对象 commit,tree 和 blob

    • Blob存储文件的内容
    • Tree存储文件的目录信息
    • Commit存储提交信息,一个Commit可以对应唯一版本的代码
  • refs 内容就是对应 Commit ID因此把ref当做指针,指向对应的Commit来表示当前Ref对应的版本.

    • Branch git checkout -b可以创建一个新分支, 分支一般用于开发阶段,是可以不断添加 Commit 进行迭代
    • Tag标签一般表示的是一个稳定版本, 指向的Commit一般不会变更
  • refs/head 下保存 分支信息

1.3 密钥生成/ 设置用户名/ 缩写

# 生成本地密钥
# ssh-keygen -t ed25519 -C "your_email@example.com"  密钥默认存在 ~/.ssh/id_ed25519.pub
ssh ssh-keygen -t rsa 
// linux 下ssh-keygen -t rsa 
    
//根据日志信息里面的 SSH KEY 存储路径找到 .ssh/id_rsa.pub 文件
//打开 git 网站,右上角用户头像,点击 settings,左侧菜单 SSH KEYS,将文件内容复制到 key 里 添加就可以了//设置名称和邮箱
git config --global user.name "Your Name"
git config --global user.email "email@example.com"# 设置简写
git config --global alias.psm 'push origin main'
git config --global alias.plm 'pull origin main'
​
git config --global alias.st 'status'
git config --global alias.ci 'commit'
git config --global alias.br 'branch'

1.3.pull &push/ 快速开始

//推过去所需要的步骤
# 1 添加 
git add .
​
# 2 提交改变 
git commit -m "描述"# 3 推送给github
git push origin main 
​
# 拉过来
git pull origin main
​
git remote add origin 仓库名

Git 有三种状态,你的文件可能处于其中之一: 已提交(committed)、已修改(modified) 和 已暂存(staged)。

  • 已修改表示修改了文件,但还没保存到数据库中。
  • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交表示数据已经安全地保存在本地数据库中。

2 远端仓库/ remote

2.1 http 和 git 协议有什么区别

  • 第一组使用 HTTPS 协议,第二组使用 SSH 协议。具体选择哪种协议取决于你的需求和配置。
  • 使用 HTTPS 协议需要提供用户名和密码,而使用 SSH 协议则需要设置密钥对。
# 用于查看当前项目中配置的所有远程仓库的详细信息。
git remote -v
origin  https://github.com/*****/tinywebserver (fetch)
origin  https://github.com/*****/tinywebserver (push)
​
origin  git@github.com:*****/simple-douyin.git (fetch)
origin  git@github.com:*****/simple-douyin.git (push)

其中

  • fetchgit fetch 命令用于从远程仓库获取最新的代码和提交历史,但不会自动合并或更新你的本地分支。它将远程仓库的内容下载到你的本地仓库,使你能够查看和比较远程分支与本地分支之间的差异。fetch 操作不会修改你的本地分支,只会更新你的本地仓库。
  • pushgit push 命令用于将你的本地分支的提交推送到远程仓库。它将你的本地分支的提交上传到远程仓库,并将远程仓库的相应分支更新为你的提交。push 操作会修改远程仓库的内容。

2.2 链接远程仓库

# 链接远程仓库,使通过网络与远程仓库进行交互。
git remote add <remote_name> <remote_url>
​
# 设置fetch 和 push 为不同的仓库
git remote set-url --add --push origin git@github. com: my_repo/git.git

查看文件内容

git cat-file 是一个用于查看 Git 对象内容的命令。Git 中的对象是存储在仓库中的基本数据单元,包括提交(commit)、树(tree)、标签(tag)和文件内容(blob)等。

使用 git cat-file 命令,你可以通过指定对象的哈希值或引用来查看对象的内容。它的基本语法如下:

 cat-file -t <对象引用>

这个命令将会返回指定对象的类型。例如,git cat-file -t abc123 将会返回对象 abc123 的类型,比如 committreetagblob

 cat-file -p <对象引用>

这个命令将会返回指定对象的内容。例如,git cat-file -p abc123 将会返回对象 abc123 的内容,比如提交信息、文件内容等。

通过使用 git cat-file 命令,你可以查看 Git 仓库中的对象的详细信息,这对于调试和了解仓库的内部结构非常有用。

希望这个解释对你有帮助。如果你还有其他问题,请随时告诉我!

3 分支操作

3.1 本地操作分支

# 查看本地分支列表
git branch
​
# 查看远程分支列表
git branch -r
​
# 新建一个叫 develop 的分支
git branch develop
# 创建一个名为 "test" 的新分支,并从 "master" 分支进行分叉。
git branch test master
​
# 切换 到 dev 分支
git checkout dev
​
# 新建并且自动切换到 develop 分支
git checkout -b dev
​
# 删除本地分支
git branch -d develop
​
​
​
​
​
#用来切换tag
git checkout v1.0
git checkout ffd9f2dd68f1eb21d36cee50dbdd504e95d9c8f7 # 后面的一长串是commit_id,是每次com
mit的SHA1值,可以根据 git log 看到。
​
#  tag<=> 稳定版本
git tag v0.0.1
​
​
​

3.2 想拉取远程仓库的 dev 分支怎么做

要拉取远程仓库的 dev 分支,可以按照以下步骤进行操作:

git fetch origin dev
  1. 使用 git fetch origin dev 命令从远程仓库拉取 dev 分支的最新代码。这将会将远程仓库的 dev 分支代码下载到你本地仓库,不会自动合并到你当前的分支。
  2. 使用 git checkout dev 命令切换到 dev 分支。如果本地还没有 dev 分支,可以使用 git checkout -b dev origin/dev 命令创建并切换到 dev 分支。

现在你已经成功拉取了远程仓库的 dev 分支,可以开始在本地与该分支进行开发和修改。记得在操作前先保存好本地的修改,以免冲突。

3.3 远程分支

  • 远程分支没有新建指令, 直接 push 就好
# 删除远程分支
git push origin --delete publish
# 通过将 <source> 设置为空,就表示没有要推送的本地分支,而只是请求删除远程分支
git push origin :develop
​
# 如果你远程的分支想取名叫 develop2 ,那执行以下代码:
git push origin develop:develop2
​
# 把 develop 分支推送到远程仓库
git push origin develop

3.4 合并分支

  • Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。在进行提交操作时,Git 会保存一个提交对象(commit object)。
  • Git 的分支,其实本质上仅仅是指向提交对象的可变指针
  • Git 又是怎么知道当前在哪一个分支上呢? 也很简单,它有一个名为 HEAD 的特殊指针。指向当前所在的本地分支(译注:将 HEAD 想象为当前分支的别名)。
  • 由于 Git 的分支实质上仅是包含所指对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以它的创建和销毁都异常高效。
# 我们在一个 featureA 分支开发完了一个功能,这个时候需要合并到主分支 master 上去
git checkout master
git merge featureA
​
# 也可以这么写
git checkout master
git rebase featureA

区别

  • rebase 跟 merge 的区别你们可以理解成有两个书架,你需要把两个书架的书整理到一起去,
  • 第一种做法是 merge ,比较粗鲁暴力,就直接腾出一块地方把另一个书架的书全部放进去,虽然暴力,但是这种做法你可以知道哪些书是来自另一个书架的;
  • 第二种做法就是rebase ,他会把两个书架的书先进行比较,按照购书的时间来给他重新排序,然后重新放置好,这样做的好处就是合并之后的书架看起来很有逻辑,但是你很难清晰的知道哪些书来自哪个书架的。

3.5 遇到冲突时的分支合并

  • 有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。
  • 此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突
# 现在在 master分支,  想要合并 dev 的内容
$ git merge dev
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
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")
Unmerged paths:
    (use "git add <file>..." to mark resolution)
    both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突 解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看 起来像下面这个样子:

# HEAD 所指向的版本
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
# 合并所指向的版本
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内 容。同时 <<<<<<< ,======= , 和 >>>>>>> 这些行被完全删除了。

3.6 多人合作冲突

远程跟踪分支是远程分支状态的引用。它们是你无法移动的本地引用。一旦你进行了网络通信, Git 就会为你移 动它们以精确反映远程仓库的状态。它们以/ 的形式命名。

假设你的网络里有一个在 git.ourcompany.com 的 Git 服务器。 如果你从这里克隆,Git 的 clone 命令会为你自动将其命名为 origin,拉取它的所有数据, 创建一个指向它的 master分支的指针,并且在本地将其命名为 origin/master。Git 也会给你一个与 origin 的master 分支在指向同一个地方的本地 master 分支,这样你就有工作的基础。

隔离性

  • 如果你在本地的 master 分支做了一些工作,在同一段时间内有其他人推送提交git.ourcompany.com 并且更新了它的 master 分支,这就是说你们的提交历史已走向不同的方向。 即便这样,只要你保持不与origin 服务器连接(并拉取数据),你的 origin/master 指针就不会移动。
  • 如果要与给定的远程仓库同步数据,运行 git fetch <remote>命令

常见开发场景

1、本地仓库有文件,远程服务器上面是新建的仓库

# 1 初始化仓库
git init test
​
# 2 在仓库中新建文件编辑内容(例如test.txt)# 3 添加到暂存区
git add test.txt
​
# 提交修改
git commit test.txt -m '提交test.txt'# 关联远程仓库, origin也是默认仓库的名字,也可以命名为其它的名字
 git remote add origin git@gitee.com:blueses/test.git
​
# 把本地仓库的master分支与远程仓库的master分支关联起来
# 把本地仓库的master分支的文件推送到远程仓库的master分支中
 git push -u origin master
​
​

2、远程服务器上面有很多代码,要拉取到本地开始开发

# 直接克隆
 git clone git@gitee.com:blueses/test.git
​
#  add、commit、pull、push 三步走

其他操作

提交操作

# 修改最近一个的 commit 信息, 修改之后, commit id 会改变
# 老的 不会删除
git commit --amend
​
# 对最近三个commit的修改, 合并commit, 修改具体的 commit message, 删除某个commit
git rebase -i HEAD~3
​
# 该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
filter --branch

日志操作

git reflog expire --expire=now --all
git gc --prune=now
​

拉取操作概念辨析

  • Clone拉取完整的仓库到本地目录,可以指定分支,深度.
  • Fetch将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息,如果需要和本地代码合并需要手动操作.
  • Pull拉取远端某分支,并和本地代码进行合并,操作等同于 git fetch + git merge,也可以通过 git pull --rebase 完成 git fetch + git rebase 操作. 可能存在冲突,需要解决冲突.
# 初始化一个新的 Git 仓库:
git init
​
# git remote add origin 远程仓库URL
git remote add origin git@github.com:username/repo.git
​
# 将远程仓库内容下载到本地:
git pull origin 主分支名称
​
# 首次拉取代码时一定会存在当前分支与远程分支不同步的问题,我们可以指定使用 rebase 策略将你的更改应用到远程更改之上:
git pull --rebase origin main
​
​
# 如何查看我有没有 ssh 权限修改 github 的内容
ssh -T git@github.com   # # 如果你想要将本地分支与远程仓库的同名分支进行关联,
git push -u origin <本地分支名称>  
# 可以使用 git push / git pull# 将会将本地的 main 分支推送到远程仓库 origin 的 master 分支。
git push origin main:master