【Git】Git命令的学习与总结
本文实践于 Learn Git Branching 这个有趣的 Git 学习网站。在该网站,可以使用 show command 命令展示所有可用命令。你也可以直接访问网站的sandbox,自由发挥。
一、本地篇
基础篇
git commit
git commit将暂存区(staging area)的修改提交到本地版本库并创建一个新的提交,新提交会指向前一个提交,就像是链表一样的结构。
这里需要我们知道Git里的重要概念:工作区(working directory)、暂存区(staging area或index)和版本库(repository)。工作区即我们所见的项目文件夹。工作区中有个.git隐藏目录,这个是版本库,暂存区就位于版本库中,此外版本库中还有创建的分支以及指向当前分支的指针HEAD。分支实际上是个文件,但它完成的功能类似于一个指针。
git commit常用的结构:
$ git commit -m "C2"
直接运行git commit会打开Git默认编辑器。
git branch
git branch用于分支管理,包括:
- 列出已有分支:git branch
- 创建新分支:git branch <branch>
- 删除分支:git branch -d <branch>
- 重命名分支:在本地重命名分支名:git branch -move <old-branch-name> <new-branch-name>,将这个修改同步到远程:git branch --set-upstream origin corrected <new-branch-name>
来创建一个名为newImage的分支:
$ git branch newImage

补充:
main分支是默认主分支,*表示当前分支所在。我们的提交记录会提交到当前分支。
上图*号依然位于main,说明当前分支仍然是main。
使用以下命令切换到新分支上:
$ git checkout newImage

Git 2.23 版本引入了
git switch <branch-name>命令来取代git checkout命令众多功能中的切换分支功能。
最后,git branch <branch-name>和git checkout <branch-name>可以合并为一条命令:
$ git checkout -b <branch-name>
git merge
git merge用于将一个或多个分支合并到当前分支上。在新建分支开发完新功能或修复完 Bug 后,我们可以将其合并回主分支。
合并bugFix分支到main分支:
$ git switch main
$ git merge bugFix

可以看到,合并分支时创建了新提交,这是非快进提交。接着,把main分支合并到bugFix:
$ git switch bugFix
$ git merge main

这是快进合并(Fast Forward)。
git rebase
git rebase是另一种分支合并的方式,称为变基,具体是把一系列的提交记录复制到另一个地方。
使用git rebase可以使得提交历史更加线性,因为git rebase可用于修剪git提交历史,而是否保存或删除原纪录,git rebase的交互模式中可以设置。
$ git rebase main

git rebase main将当前分支(*所在)bugFix从与main分支的公共祖先提交部分开始的提交记录复制到以main分支的最新提交为起始的地方,但 复制不是真的复制,是解决冲突后的复制,如图复制后的C3'提交已经与原提交C3不同了。
git rebase main中的main就是基分支,当前分支bugFix就是变基分支。
我们可以主动指定基分支和变基分支:git rebase main bugFix。
高级篇:在提交树上移动
HEAD 简介与 HEAD 分离
HEAD 是一个指针,通常指向当前分支名,偶尔也会指向当前提交。
$ git checkout C1 # 切换到 C1 提交
$ git checkout main # 切换到 main
$ git commit -m "C2" # HEAD 指向的 main 指向 C2
$ git checkout C2 # 切换到 C2 提交

像git checkout C1这样将 HEAD 指针指向提交C1的行为称为 HEAD 分离(Detached HEAD)。分离前,HEAD 指向的是分支引用 main。git checkout C1中的C1其实是提交的HASH值。
查看提交记录的哈希值
$ git log

HASH 值很长,但我们只需要其前面几位可以唯一标识提交的即可,例如63dbb453f...我们取63dbb。
查看 HEAD 指向
$ git switch main
$ cat .git/HEAD
refs/heads/main
如果 HEAD 指向引用而非提交,也可以像下面查看 HEAD 指向:
$ git symbolic-ref HEAD
相对引用
前文使用 HASH 值来指定提交记录,这是直接引用,难免不方便,Git 提供了相对引用的方式来指定提交:
<branch>^:branch指向的提交的上一个提交。<branch>^^:branch指向的提交的前面第二个提交。<branch>~<num>:branch指向的提交前面第num个提交。
$ git checkout main^ # 将HEAD指向main分支指向提交的前一个提交
强制修改分支位置
除了切换分支,相对引用用的最多的地方是移动分支。
$ git branch -f main HEAD~3 # 将main分支移动到HEAD指向提交的前第3个提交
如果要移动的分支不存在会自动创建。
撤销变更
git reset
git reset命令将当前分支回退到直接引用或相对引用指向的提交记录,之后的提交记录就撤销了。
$ git reset HEAD^

C2提交被reset后,就不存在于本地版本库中,但是其变更还在,只不过处于未暂存状态。
git reset只对本地分支有效,无法回退远程分支。
进行git reset后,如果进行推送,Git 会提示远程仓库较新需要git pull,但是git pull后你的代码被远程仓库覆盖,如果想要回退生效,则需要追加-f进行强制推送。
git revert
git revert会创建新提交来撤销或恢复更改。这个要求你的working tree为空,即当前分支没有做新的修改。
$ git revert HEAD^^

如上图,我们恢复C1提交(HEAD^^)为一个新提交。
移动提交记录
git cherry-pick
git chery-pick用于把一些提交复制到当前提交(HEAD)的下面。
$ git cherry-pick C2 C4

交互式 rebase
git rebase 后追加 --interactive 或 -i 选项会打开一个窗口(你配置的编辑器)显示将要被复制到目标分支的提交的哈希值和提交说明。
一个打开的示例窗口如下:
pick 63dbb45 2# Rebase 88e2af2..63dbb45 onto 88e2af2 (1 command)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# create a merge commit using the original merge commit's
# message (or the oneline, if no original merge commit was
# specified); use -c <commit> to reword the commit message
# u, update-ref <ref> = track a placeholder for the <ref> to be updated
# to this position in the new commits. The <ref> is
# updated at the end of the rebase
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#

使用git rebase经常会遇到要解决冲突的情况,解决冲突后,执行git add和git rebase --continue。解决冲突是在两种修改中手动选择一项或按需求地合并它们。



杂项
只复制一个提交
有时候,我们开发完一个功能,需要与主分支进行合并时,会希望只合并我想要的那个提交。
我们知道,使用git merge的合并有快进合并和非快进合并两种。但是这两种合并会将我们不需要的提交也包含在主分支中。
这时候,我们可以使用git cherry-pick或git rebase -i来完成。

如上图,我想要将修复问题后的提交bugFix合并到main。
如果使用git merge:
$ git checkout main
$ git merge bugFix

这使得主分支 main 中就包含了 C2、C3 这些提交。
使用git cherry-pick:
$ git checkout main
$ git cherry-pick C4
$ git branch -f bugFix main

git tag
git tag为提交记录打上标签,它可以像分支一样引用,但不会像分支一样移动。
$ git tag V1

$ git tag V2 C0

git describe
git describe查找离指定引用最近的标签。

git describe main输出v1_2_gC2,git describe side输出v2_1_gC4。
git describe <ref>的输出格式:<标签>_<数字>_g<提交的哈希值>。数字的意思是从标签到指定提交的提交数量。
高级话题
多次 rebase

$ git checkout another
$ git rebase side
$ git rebase bugFix
$ git rebase main
$ git branch -f main another

相对引用^中选择 parent 提交记录
相对引用^可以像~一样在后面加个数字,该数字表示选择第几个 parent 提交记录。^后加数字直观上与 ~ 加数字的区别是前者是横向,后者是纵向。
$ git checkout main^2

^和~的链式操作;
$ git checkout HEAD~^2~2

二、远程篇
Git 远程仓库基本操作
git clone
git clone命令用于从远程仓库(如Github、Gitee等)拷贝你需要的仓库。远程仓库可看作是你的本地仓库在另一台电脑上的拷贝。
$ git clone <远程仓库URL>
URL例子:https://github.com/dawnkylin/demo,这个URL采用了HTTP传输协议,除此之外,还可以使用git://或者使SSH协议的user@server:path/to/repo.git。

远程分支
上一节中的克隆产生的o/main分支就是远程分支,o是远程仓库名,一般是origin,图示使用简写代替。你使用git clone克隆完一个仓库时,已经将远程仓库名设置为origin了。
查看远程仓库信息:
$ git remote -v
修改远程仓库名:
$ git remote rename <远程仓库名>
远程分支反映了远程仓库的状态。
切换到远程分支会自动切换到 HEAD 分离状态。
$ git checkout o/main

git fetch
git fetch从远程仓库下载缺失的提交记录,并更新远程分支。
$ git fetch <远程仓库URL>
git fetch不会改变你的本地分支状态,也就是不会改变你的本地仓库文件。
示例:

执行git fetch后:

git pull
使用git fetch只更新了远程分支,并未更新本地分支,还需要我们进行进一步合并,使用下面方法之一:
- git cherry-pick origin/main
- git merge origin/main
- git rebase origin/main
git pull 命令将拉取和合并操作结合在了一起,相当于git fetch和git merge的结合。
git push
git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。
查看 push.default 值。
$ git config --get push.default
push.default 通常具有以下几种值:
simple:这是 Git 2.0 及以后版本的默认值,它会将当前分支的 push 操作限制为其上游(通常是 origin 远程仓库)的同名分支。current:将 push 操作限制为当前分支。nothing:禁用默认的 push 行为,需要明确指定要 push 的分支和远程仓库。matching:这是 Git 1.x 版本中的默认行为,它会将本地的所有分支与远程仓库的同名分支进行匹配,然后将它们都 push 到远程仓库。
修改 push.default:
$ git config push.default <new_value>
偏离的提交历史
当你使用 git push 推送代码时,会遇到无法推送,要先与远程仓库合并的提示。这是由于远程仓库已经被你的同事修改了,你调用的 API 可能已经不存在或改名了,也就是发生了冲突。

如何解决冲突?
① 使用 git rebase
$ git fetch
$ git rebase o/main
$ git push o main

② 使用 git merge
$ git fetch
$ git merge o/main
$ git push o main

使用 git merge 会多一个合并提交。与git pull达到相同的结果。
③ 使用 git pull --rebase,即 git fetch 与 git rebase 的结合
$ git pull --rebase
$ git push
Git 远程仓库高级操作
远程追踪
main 分支默认指定为跟踪远程分支 origin/main ,跟踪的意思是指定了 origin/main 为 push 的目的地和 fetch 后合并的目标。
如何自己设置分支跟踪远程分支?
方式一:
$ git checkout -b <local branch> <remote branch>
比如 git checkout -b foo origin/main。
方式二:
$ git branch -u <remote branch> <local branch>
例如 git branch -u origin/main foo,如果当前就在 foo 分支,还可以省略 foo。
git push 的参数
实际 git push 的语法是:
$ git push <remote> <place>
意思是将 remote 的 place 分支没有的而本地 place 分支有的提交记录添加到 remote 的 place 分支。不仅会更新远程的 place 分支,也会更新本地的 remote/place 分支。
而 git push 没有参数时,会根据当前分支和它所追踪的远程分支来自动设置参数。
git push 的参数 2
将本地 source 分支推送到远程仓库的 destination 分支:
$ git push origin <source>:<destination>
准确地说,source 不一定是分支,也可能是标签、提交的 HASH 部分值和相对引用等等 Git 可以识别的位置。如果目的分支 destination 不存在,Git 会帮你自动创建的。
git fetch 的参数
$ git fetch origin foo
拉取远程仓库 origin 的远程分支 foo 的新提交,并放到本地的远程追踪分支 origin/foo 上,而不会影响 foo 分支。
也可以使用 <source>:<destination> 的参数格式:
$ git fetch origin foo~1:bar
上面命令的作用是将远程 foo 分支的上一个提交拉取到本地的 bar 分支上。

如果 bar 分支不存在就新建,这个和 git push 的参数行为是一致的。
没有指定参数的 git fetch 则会拉取所有提交记录。
source 参数为空的 git push 和 git fetch
1)git push orgin :foo 传空值 source 删除了远程的 foo 分支,连带着删除了本地的 origin/foo 分支。
2)git fetch origin :foo 则会在本地新创建一个 foo 分支。
相关文章:
【Git】Git命令的学习与总结
本文实践于 Learn Git Branching 这个有趣的 Git 学习网站。在该网站,可以使用 show command 命令展示所有可用命令。你也可以直接访问网站的sandbox,自由发挥。 一、本地篇 基础篇 git commit git commit将暂存区(staging areaÿ…...
前端工程化面试题 | 18.精选前端工程化高频面试题
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
大公司的工程师是怎么废掉的...
大家好,我是砖一。 此文作者以嵌入式工程师为基本视角,细说了从初阶到高阶工程师的资质需求,并提示工程师职业道路上的陷阱。可供参考。 一,基础知识 一个嵌入式工程师,很多都是从51单片机或者STM32单片机开始&…...
将yolov8权重文件转为onnx格式并在c#中使用
yolo模型转ONNX 在yolov8中,我们将训练结果的.pt权重文件转换为onnx格式只需要使用ultralytics库中的YOLO类,使用pip安装ultralytics库,然后执行下面python代码 from ultralytics import YOLO# 加载YOLOv8模型 model YOLO("best.pt&q…...
在Spring Boot启动时禁止自动配置数据源相关的组件、@SpringBootApplication
一、SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解 在Spring Boot启动时禁止自动配置数据源相关的组件。 SpringBootApplication(exclude {DataSourceAutoConfiguration.class})注解的使用案例 这个注解通常应该写在微服务项目的主启动类上&…...
程序人生:不积跬步无以致千里
程序人生 癸卯年冬月,往渭南韩城,拜访司马迁祠。入门攀爬而上,至人有困乏之时,抬头现:高山仰止。归路下山,始现三官洞,遥想西汉时三官洞,出口处刻意再拜别:高山仰止。泪…...
通过二叉树例题深入理解递归问题
目录 引入: 例1:二叉树的前序遍历: 例2: N叉树的前序遍历: 例3:二叉树的最大深度: 例4:二叉树的最小深度 例5:N叉树的最大深度: 例6:左叶子…...
【Android 协程常见用法】
我们这里只讲解一下,协程在Android项目中常见用法,原理知识不在进行说明了。 依赖 lifecycleScope只能在Activity、Fragment中使用,会绑定Activity和Fragment的生命周期。依赖库: implementation androidx.lifecycle:lifecycle…...
python 进程笔记一 (概念+示例代码)
1. 进程的概念 进程是资源分配的最小单位,也是线程的容器,线程(python 线程 (概念示例代码))是CPU调度的基本单位,一个进程包括多个线程。 程序:例如xxx.py是一个程序 进程…...
各中间件数据库默认访问端口总结
说明 在生态丰富的开发环境下,我们常常需要接触很多中间件产品,中间件默认的连接端口以及可视化ui访问端口也时不时的需要用到,这里循序渐进做好登记,以备查阅! 中间件/数据库名称默认端口管理台端口默认账号密码rabbi…...
鲲鹏arm64架构下安装KubeSphere
鲲鹏arm64架构下安装KubeSphere 官方参考文档: https://kubesphere.io/zh/docs/quick-start/minimal-kubesphere-on-k8s/ 在Kubernetes基础上最小化安装 KubeSphere 前提条件 官方参考文档: https://kubesphere.io/zh/docs/installing-on-kubernetes/introduction/prerequi…...
python 函数-02-返回值注释格式
01 函数返回值 1)python中函数可以没有返回值,也可以有通过return的方式 – 【特殊性,区别于java c#等】 2)返回值可以是一个或者多个,多个时通过逗号隔开 – 【特殊性,区别于java c#等】 3)多…...
【前端素材】推荐优质后台管理系统Upcube平台模板(附源码)
一、需求分析 后台管理系统在多个层次上提供了丰富的功能和细致的管理手段,帮助管理员轻松管理和控制系统的各个方面。其灵活性和可扩展性使得后台管理系统成为各种网站、应用程序和系统不可或缺的管理工具。 当我们从多个层次来详细分析后台管理系统时࿰…...
可视化 RAG 数据 — 用于检索增强生成的 EDA
原文地址:Visualize your RAG Data — EDA for Retrieval-Augmented Generation 2024 年 2 月 8 日 Github:https://github.com/Renumics/rag-demo/blob/main/notebooks/visualize_rag_tutorial.ipynb 为探索Spotlight中的数据,我们使用Pa…...
数学建模论文、代码百度网盘链接
1.[2018中国大数据年终总决赛冠军] 金融市场板块划分与轮动规律挖掘与可视化问题 2.[2019第九届MathorCup数模二等奖] 数据驱动的城市轨道交通网络优化策略 3.[2019电工杯一等奖] 露天停车场停车位的优化设计 4.[2019数学中国网络数模一等奖] 基于机器学习的保险业数字化变革…...
mysql 迁移-data目录拷贝方式
背景:从服务器进水坏掉,50多G的数据库要重新做主从,但以导入导出的方式太慢,简直是灾难性的,一夜都没好,只好想到了拷贝mysql数据文件的方式 拷贝的数据文件的前提 1.数据库版本必需一致(可以…...
学习 LangChain 的 Passing data through
学习 LangChain 的 Passing data through 1. Passing data through2. 示例 1. Passing data through RunnablePassthrough 允许不改变或添加额外的键来传递输入。这通常与 RunnableParallel 结合使用,将数据分配给映射中的新键。 RunnablePassthrough() 单独调用&…...
C# OpenVINO PaddleSeg实时人像抠图PP-MattingV2
目录 效果 项目 代码 下载 C# OpenVINO 百度PaddleSeg实时人像抠图PP-MattingV2 效果 项目 代码 using OpenCvSharp; using Sdcb.OpenVINO; using System; using System.Diagnostics; using System.Drawing; using System.Security.Cryptography; using System.Text; us…...
【Android 11】AOSP Settings WIFI随机MAC地址功能
AOSP Settings WIFI随机MAC地址功能 背景 最近客户提出了想要实现随机WIFIMAC地址的功能(我们默认WIFI的MAC地址是固定的)。网上搜到了一篇不错的文章,本次改动也是基于这个来写的。 由于客户指定使用的settings是AOSP的,所以在…...
dmrman备份还原
脱机还原工具-dmrman 前言 根据达梦官网文档整理 一、概述 DMRMAN 命令行设置参数执行又可分为命令行指定脚本、命令行指定语句两种执行方式。 指定语句 $ DMRMAN RMAN>BACKUP DATABASE/dmdata/data/DAMENG/dm.ini;指定脚本 创建一个名为 cmd_file.txt 的文件&#x…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
Linux操作系统共享Windows操作系统的文件
目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项,设置文件夹共享为总是启用,点击添加,可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download(这是我共享的文件夹)&…...
