Git技术

引言

Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比,使用 bash 命令实现版本控制,常用命令是 git clone、git push、git add、git commit、git checkout、git pull、git merge等,远端托管使用 Github、GitLab 和 gitee 等,Github 远程仓库地址的默认代称是 origin,Git 初始化本地仓库的默认分支对象名字是 main 或 master

add
commit
checkout
push
fetch/clone
pull
工作区
暂存区
本地仓库
远程仓库

Git 在进行首次提交之前工作区将处于“浮动状态”,因为本地的当前目录中的文件尚未与 Git 的本地仓库产生任何特定状态关联,但是依旧可以认为本地的当前目录中的文件在工作区中,当进行了首次提交后工作区将明确的表示为当前分支的检出

暂存区(Staging Area 或 Index)和本地仓库(Local Repository)都位于 .git 目录中。当你在一个目录中执行 git init 命令来初始化一个新的 Git 仓库时,Git 会创建一个 .git 子目录。这个目录包含所有必需的元数据和对象数据库,用于维护仓库的完整历史记录和版本信息,其中主要包括以下内容

  • objects/:这个目录存储了所有的 blob、tree 和 commit 对象,这些对象代表了仓库的内容和历史。大部分仓库的数据都存储在这里
  • index:这个文件(也经常被称为 “staging area” 或 “cache”)代表了暂存区。它包含了下一次提交将包含的所有信息,即实际上持有了下一个提交的预期快照
  • HEAD:这是一个指向当前检出的分支的引用(一般代表该分支的最新一次提交)
  • config:这个文件存储了项目级别的配置设置
  • refs/:这个目录包含指向数据(如分支和标签)的引用
  • hooks/:这个目录包含脚本,这些脚本可以在特定的 Git 操作之前或之后自动运行
  • info/:这个目录包含一个默认的 exclude 文件,用于指定本地忽略的模式(与 .gitignore 功能类似,但不会被提交到仓库)
  • logs/:存储了一系列的文件,记录了仓库的引用变化历史,这有助于支持 git reflog
  • remotes/:存储了关于远程仓库的信息

Git 可使用 https 协议、ssh 协议 和 git 协议与远端托管建立通信

  • https 协议的网络地址以 https:// 开头,是 http + ssl 组成的安全网络协议,http 是建立在应用层,ssl 是建立在传输层,首先需要身份授权验证(使用账号和密码)然后进行加密传输数据(账号密码以及数据传输均使用 ssl 加密)

  • ssh 协议的网络地址以 ssh:// 开头,是建立在应用层的安全网络协议,不仅可以加密传输数据还可以进行身份授权验证,需要本地存储非对称密钥的私钥,远端托管绑定非对称密钥的公钥

    github中常用的 git@ 实际上就是使用 ssh 协议,相当于 ssh://git@

  • git 协议的网络地址以 git:// 开头,Git 的原生传输协议,这种协议是只读的,非常高效,但它不支持任何类型的身份验证

一般工作流

1. 创建 Ssh Key 作为本地与 Github 通信的密钥(Gpg Key 类似)

  • 终端执行 ssh-keygen -t rsa -f <生成路径> -C <Github 邮箱地址> 在指定位置生成 .ssh 文件夹,其中包含 id_rsa 私钥与 id_rsa.pub 公钥,在自己 Github 账户里的设置的 Ssh Key 中输入 id_rsa.pub 公钥的内容绑定,如果本地的 id_rsa 私钥的路径不在系统环境变量中则终端执行 git config --global core.sshCommand "ssh -i <私钥文件路径>"
  • 终端执行 ssh -T git@github.com 可以验证是否绑定成功,返回 Hi <Github 账户名字> ! You've successfully authenticated, but GitHub does not provide shell access. 表示成功
  • 终端执行 git config --global user.name <你的名字>git config --global user.email <你的邮箱地址> 配置 Git 用户的名字与邮箱地址用于提交时的信息记录,终端执行 git config -lgit config --list 查看 Git 配置信息
  • 上述 config 命令中添加参数 --global 则设置全局有效否则仅当前工作区有效

2. 使用 Git 初始化本地项目文件

  • 在本地项目文件的根目录启动终端或直接启动终端执行 cd <本地项目文件路径>
  • 终端执行 git init 生成一个 .git 文件夹(实现了本地仓库与暂存区等概念以及保存各分支对象的快照等),初始化后终端执行 git branch -m main(表示将当前分支命名为 main),可在终端运行 git config --global init.defaultBranch main 使得每次初始化后得到到分支都命名为 main
  • 在 Github 新建一个空的新仓库,其默认分支对象名为 main,终端输入 git remote add origin git@github.com:<Github 账户名字>/<仓库名字>.git 设置远程仓库地址并代称 origin
  • 在工作区创建一个初始 README.md 文件,终端执行 echo "# <本地项目文件路径>" >> README.md 或手动在工作区创建一个 README.md 文件
  • 终端执行 git add README.mdgit add *或.*或. 表示当前工作区中的全部文件)将工作区的 README.md 文件添加到暂存区,终端执行 git commit -m <注释信息> 将暂存区的文件提交给本地仓库并包含注释信息,这将形成一份本地项目文件快照
  • 终端执行 git status 可以查看当前的状态(它将告诉你哪些文件已经修改但还没有暂存,哪些文件已经暂存但还没有提交,以及哪些文件是新的或未被跟踪的),终端执行 git ls-files 可以列出已提交的和暂存中的文件,终端执行 git commit --amend 可以将新的操作合并到上一次提交中

3. 从本地仓库往远程仓库推送

  • 终端执行 git push -u origin main-u 表示设置 push 操作的远程仓库地址),之后直接 git push 即可 GIt 将默认使用第一次的值

4. 从远程仓库往工作区拉回

  • 终端执行 git pull origin main:main (与当前分支对象合并可以省略 :main)从远程仓库往工作区拉回,实际上是 git fetch origin maingit merge FETCH_HEAD 或 origin/main 的组合(FETCH_HEAD 是一个记录在本地的版本链接,指向着当前从远程仓库取下来的分支对象 origin/main)即获取远程仓库到本地仓库并整合分支对象,合并到本地分支对象中

更多常见用法

终端执行 git 查看指令

usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [--super-prefix=<path>] [--config-env=<name>=<envvar>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone             Clone a repository into a new directory
   init              Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add               Add file contents to the index
   mv                Move or rename a file, a directory, or a symlink
   restore           Restore working tree files
   rm                Remove files from the working tree and from the index
   sparse-checkout   Initialize and modify the sparse-checkout

examine the history and state (see also: git help revisions)
   bisect            Use binary search to find the commit that introduced a bug
   diff              Show changes between commits, commit and working tree, etc
   grep              Print lines matching a pattern
   log               Show commit logs
   show              Show various types of objects
   status            Show the working tree status

grow, mark and tweak your common history
   branch            List, create, or delete branches
   commit            Record changes to the repository
   merge             Join two or more development histories together
   rebase            Reapply commits on top of another base tip
   reset             Reset current HEAD to the specified state
   switch            Switch branches
   tag               Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch             Download objects and refs from another repository
   pull              Fetch from and integrate with another repository or a local branch
   push              Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some concept guides. 
See 'git help <command>' or 'git help <concept>' to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
  • 拷贝文件

    git clone <远程仓库地址> // 拷贝 Git 仓库到本地仓库

  • 删除文件

    git rm <文件名字> // 删除工作区和暂存中的文件
    git rm --cached <文件名字> // 仅删除暂存中的文件并设置为未跟踪状态,这使得在一下次提交时Git会删除远端的该文件
    git restore --staged <文件名字> // 撤销添加到暂存中的文件在一下次提交时不会删除该文件

  • 储藏文件

    git stash // 保存当前工作区和暂存区的更改
    git stash save "my descriptive message" // 保存当前工作区和暂存区的更改为储藏添加一个描述性的消息
    git stash list // 查看所有的储藏列表
    git stash apply stash@{n} // 将第n个储藏的修改应用到当前工作区
    git stash pop stash@{n} // 将第n个储藏的修改应用到当前工作区,并在储藏列表中删除该储藏
    git stash drop stash@{n} // 删除第n个储藏而不应用
    git stash clear // 删除所有的储藏
    git stash show stash@{n} // 查看储藏的内容和当前HEAD之间的差异

  • 重置提交

    git reset // 默认行为是 git reset --mixed HEAD,重置暂存区到当前的 HEAD(也就是最近的提交),工作目录中的文件不会被更改
    git reset --soft HEAD^ // 回退到当前版本的父版本即上一个版本,使用 --soft 参数后暂存区和工作目录中的文件都不会被改变,仅仅是相当于取消了上一次的 commit 记录
    git reset --hard HEAD~3 // 回退上上上一个版本(HEAD~3 是当前提交的上 3 次提交),使用 --hard 参数会将暂存区与工作区都回到指令版本,并删除之前的所有信息提交
    git reset --hard origin/main // 将本地的状态回退到和远程的一样
    git revert HEAD // 不同于 git reset 而会创建一个新的提交,提交所做的更改是与 HEAD 指向的最近一次提交所做的更改完全相反的,因此抵消了上一次提交从而起到了恢复的作用,最终的结果从代码的角度看,它就好像 HEAD 提交从未发生过。从提交历史的角度看,原始的 HEAD 提交以及撤销它的新提交都清晰地保留在历史中

  • 分支操作

    git branch <分支对象名字> // 创建分支对象
    git branch -d <对象分支名字> // 删除分支对象
    git push origin --delete <对象分支名字> // 删除远程仓库分支对象
    git checkout <分支对象名字> // 检出分支对象(切换分支对象)
    git checkout -b <分支对象名字> // 创建并检出分支对象
    git cherry-pick <commit-hash> // 可以将某个特定的提交应用到其他分支对象

  • 合并分支

    git merge <目标合并分支对象名字>
    “Git首先找到当前分支和目标分支的公共最近祖先的快照,Git 使用三个点来完成合并操作:公共祖先、当前分支的最新提交和目标分支的最新提交,如果合并过程中有冲突,操作会停止,需要用户手动解决这些冲突,解决冲突后,你需要再次添加并提交以完成合并操作,总的来说merge总是在向前推进提交,不会修改任何提交历史”
    git merge --abort // 退出合并

  • 变基分支

    git rebase <目标基底分支对象名字>
    “Git首先找到当前分支与目标基底分支的公共最近祖先的快照,然后暂存当前分支相对于该祖先的历次提交,然后将当前分支指向目标基底分支, 最后将实先暂存的历次提交的快照应用到目标基底分支,同样的遇到冲突会停止,当手动解决冲突后,你需要执行 git rebase --continue(即再次添加并提交)以完成变基操作,rebase 相较于 merge 会在合并分支对象的基础上优化整个分支对象的历史,使其变得像一条直线,简洁提交历史的同时也使得快照的顺序不同于真实的提交顺序”
    git rebase --abort // 退出变基
    git rebase -i <目标基底分支对象名字> // 将使用交互式变基,Git将自动打开一个文档,其中例举了变基过程中所涉及的历史提交,允许用户自行编辑变基的逻辑,文档保存后将自动开始变基

  • 创建标签

    git tag <标签名字> // tag 是指向本地的提交的指针,需要通过 git push origin <标签名字> 单独推送到远程仓库,本地多个标签可一次性推送 git push origin --tags
    git tag -a <标签名字> <Commit ID> -m "release 0.1 version" // 为 Commit ID 号所代表提交添加标签并添加附注标签 (-a 意为带注解的会记录标签时间等)
    git tag -l // 查看本地标签
    git tag -d <标签名字> // 删除本地 tag
    git push origin :<标签名字> // 远程 tag 的删除
    git ls-remote --tags origin // 查看远程的标签
    git checkout -b <分支对象名字> <标签名字> // 等价于 git checkout -b <分支对象名字> <Commit ID> 创建新的分支并把标签名字所对应的提交放入工作区

  • 查看历史

    git log // 查看提交记录
    git blame <文件名字> // 查看指定文件的历史修改记录

解决远端冲突

把远程仓库的分支对象 master 合并到分支对象 main 上,应当在本地仓库中合并分支对象,发生冲突,方便解决

  • 把远程仓库的分支对象 main 拷贝一份到本地

  • 本地分支对象上创建一个分支对象 master,把远程仓库的分支对象 master 拷贝到本地仓库的分支对象 master,在本地将 main 和 master 分支对象合并为 main

  • 解决冲突后推送到远程仓库的分支对象 main 再删除远程仓库的 master 分支对象,实现远程仓库的 main 与 master 分支对象的合并

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昊大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值