笔记:Git 学习总结
注:本文参考整理自网络资源,个人学习总结
一、Git相关概念
1.1 Git是什么
Git是一款分布式版本控制系统,Git不需要联网,在本机就可以使用
通常有两个主要用途:代码备份和代码版本控制
1.2 Git、Github的关系
Github是用于版本控制和协作的代码托管平台,可以托管各种Git版本库,并提供一个web界面
Github是代码托管平台,是协作的工具;而Git是版本控制工具
1.3 Git/Github相关概念
Repository-仓库
Issue-问题,议题
Star-点赞
Fork-分支
Pull Request-拉取请求
Watch-跟踪
Gist-代码片段
master分支-主分支
develop分支-开发分支,从master分支上检出,
release分支-发布分支,从develop分支检出,用于发布前的测试
feature分支-功能分支,从develop分支检出,用来开发新功能或项目维护
fix分支-补丁分支,由develop分支检出,用作bug修复,临时性分支
hotfix分支-热补丁分支,该分支由master分支检出,进行线上版本的bug修复,临时性分支
1.4 Git如何使用
Git的工作就是创建和保存项目的快照及与之后的快照进行对比
一般工作流程如下:
克隆 Git 资源作为工作目录。
在克隆的资源上添加或修改文件。
如果其他人修改了,你可以更新资源。
在提交前查看修改。
提交修改。
在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
工作区:
电脑里能看到的目录
版本库:
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
暂存区:
stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,
把暂存区有时也叫作索引(index)
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage, index),
标记为 "master" 的是 master 分支所代表的目录树
当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,
同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 "git rm --cached <file>" 命令时,会直接从暂存区删除文件,工作区则不做出改变。
当执行 "git checkout ." 或者 "git checkout -- <file>" 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
当执行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
二、Git用法
常用命令
创建密钥
1 2 3 4 5 6 7 8 9 | #本地创建密钥 $ ssh-keygen -t rsa -C "your_email@youremail.com" #查看本地密钥 $ cat ~/.ssh/id_rsa.pub #验证密钥 $ ssh -T git@github.com $ ssh -T git@gitee.com |
初始化
1 2 3 4 5 | # 在当前目录新建一个Git代码库 $ git init # 下载一个项目和它的整个代码历史 [Git only],从Git仓库拷贝项目 $ git clone [url] |
执行git init命令后,Git仓库会生成.git目录,包含资源的所有元数据,其它目录保持不变
配置
Git 用户的配置文件位于 ~/.gitconfig
Git 单个仓库的配置文件位于 ~/$PROJECT_PATH/.git/config
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 列举所有配置 $ git config -l # 为命令配置别名 $ git config --global alias.co checkout $ git config --global alias.ci commit $ git config --global alias.st status $ git config --global alias.br branch # 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]" # 设置额外颜色,便于阅读 $ git config --global color.ui true |
增删文件
把文件名 file1 添加到 .gitignore 文件里,Git 会停止跟踪 file1 的状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # 添加当前目录的所有文件的更改到暂存区 $ git add . # 添加当前目录的所有文件到暂存区 $ git add -A # 添加指定文件到暂存区 $ git add <file1> <file2> ... # 添加指定目录到暂存区,包括其子目录 $ git add <dir> # 删除工作区文件,并且将这次删除放入暂存区 $ git rm [file1] [file2] ... # 停止追踪指定文件,但该文件会保留在工作区 $ git rm --cached [file] # 改名文件,并且将这个改名放入暂存区 $ git mv [file-original] [file-renamed] # 用于取消已缓存的内容,将暂存区修改撤销掉 $ git reset HEAD |
分支
使用分支意味着可以从开发主线上分离开来,然后在不影响主线的同时继续工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 列出所有本地分支 $ git branch # 列出所有本地分支和远程分支 $ git branch -a # 新建一个分支,但依然停留在当前分支 $ git branch [branch-name] # 新建一个分支,并切换到该分支 $ git checkout -b [new_branch] [remote-branch] # 切换到指定分支,并更新工作区 $ git checkout [branch-name] # 合并指定分支到当前分支 $ git merge [branch] # 选择一个 commit,合并进当前分支 $ git cherry-pick [commit] # 删除本地分支,-D 参数强制删除分支 $ git branch -d [branch-name] # 删除远程分支 $ git push [remote] :[remote-branch] |
提交
Git 为每一个提交记录你的名字与电子邮箱地址,所以第一步需要配置用户名和邮箱地址
如果觉得 git add 提交缓存的流程太过繁琐,Git 也允许你用 -a 选项跳过这一步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 提交暂存区到仓库区,用于较短的提交消息 $ git commit -m [message] # 添加文件并提交一次 $ git commit filename -m [message] # 提交工作区与暂存区的变化直接到仓库区 $ git commit -a # 添加文件并提交文件 $ git commit -am # 提交时显示所有 diff 信息 $ git commit -v # 提交暂存区修改到仓库区,合并到上次修改,并修改上次的提交信息 $ git commit --amend -m [message] # 上传本地指定分支到远程仓库 $ git push [remote] [remote-branch] # 添加标签 $ git tag -a 选项意为 "创建一个带注解的标签" -d 删除指定标签 |
拉取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 下载远程仓库的所有变动 (Git only) $ git fetch [remote] # 显示所有远程仓库 (Git only) $ git remote -v # 显示某个远程仓库的信息 (Git only) $ git remote show [remote] # 增加一个新的远程仓库,并命名 (Git only) $ git remote add [remote-name] [url]
# 删除远程仓库 $ git remote rm [remote-name] # 取回远程仓库的变化,并与本地分支合并,(Git only), 若使用 Git-SVN,请查看第三节 $ git pull [remote] [branch] # 取回远程仓库的变化,并与本地分支变基合并,(Git only), 若使用 Git-SVN,请查看第三节 $ git pull --rebase [remote] [branch]
|
撤销
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # 恢复暂存区的指定文件到工作区 $ git checkout [file] # 恢复暂存区当前目录的所有文件到工作区 $ git checkout . # 恢复工作区到指定 commit $ git checkout [commit] # 重置暂存区的指定文件,与上一次 commit 保持一致,但工作区不变 $ git reset [file] # 重置暂存区与工作区,与上一次 commit 保持一致 $ git reset --hard # 重置当前分支的指针为指定 commit,同时重置暂存区,但工作区不变 $ git reset [commit] # 重置当前分支的HEAD为指定 commit,同时重置暂存区和工作区,与指定 commit 一致 $ git reset --hard [commit] # 新建一个 commit,用于撤销指定 commit $ git revert [commit] # 将未提交的变化放在储藏区 $ git stash # 将储藏区的内容恢复到当前工作区 $ git stash pop |
查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # 查看工作区文件修改状态 $ git status # 输出工作区文件修改状态的精简信息 $ git status -s # 查看工作区文件修改具体内容,尚未缓存的改动,查看工作区和暂存区差别 $ git diff [file] # 查看暂存区文件修改内容,已缓存的改动,查看暂存区和仓库差别 $ git diff --cached [file] # 查看工作区和仓库差别 $ git diff HEAD # 查看版本库修改记录 $ git log # 查看某人提交记录 $ git log --author=someone # 查看某个文件的历史具体修改内容 $ git log -p [file] # 查看某次提交具体修改内容 $ git show [commit] # 显示存储库中提交列表的摘要,显示提交ID和提交消息的较短版本 $ git log --oneline # 查看命令记录 $ git reglog |
git status 显示你上次提交更新后的更改或者写入缓存的改动, 而 git diff 一行一行地显示这些改动具体内容
完整操作过程
1,初始化仓库:git init
2,添加用户信息
git config [--global] user.name "[name]"
git config [--global] user.email "[email address]"
3,生成密钥,关联远程仓库
ssh-keygen -t rsa -C "your_email@youremail.com"
4,克隆远程仓库项目:git clone
5,从工作区提交到暂存区:git add 目录名称(添加需要提交的目录名称)
6,从暂存区提交到本地仓库:git commit -m "备注说明"(提交至本地仓库,并简单说明)
7,关联远程仓库:git remote add origin ssh://XXXXXXXXXXXXX.git (如果为第一次使用需要重定向提交的路径)
7,从本地仓库提交到远程仓库:git push -u origin master
三、Git资料合集
git官网:http://git-scm.com
git手册:http://git-scm.com/docs
网友整理的Git@osc教程,请点击这里;
一份很好的 Git 入门教程,请点击这里;
git快速入门(gif动画版),请点击这里;
Git工作机制
.git的目录树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | MacBook-Pro:wuya eleme$ tree -a . └── .git ├── HEAD ├── config ├── description ├── hooks │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── fsmonitor-watchman.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ ├── pre-receive.sample │ ├── prepare-commit-msg.sample │ └── update.sample ├── info │ └── exclude ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags 9 directories, 15 files |
Objects目录是存储文件变化的核心
文件夹放入到暂存区后,并不会马上在objects中显示,commit后才会
Objects下存放的文件名就是根据SHA1算法哈希的“指纹”,为了能够在本仓库中和其他文件区分出来。
文件内容就是Git将信息压缩后形成的二进制文件。
通过git cat-file [-t] [-p],可以看到Object的类型与文件的内容
refs目录就是用来记录当前对分支的引用信息,包括本地分支,远程分支,标签。
heads记录的是本地所有分支,remotes和HEAD一样,指向对应的某个远程分支。
这个hash值就是commit节点的hash值,而HEAD就是存储当前在哪个本地分支
git Object有三种类型:Blob、Tree、Commit
简单来说,文件都被存储为Blob类型,文件夹则为Tree类型,每次提交的节点被存储为Commit类型数据。因此,Git会以这三种类型来存储我们的文件。简单看下目录存储的映射关系:
每一次commit,都会生成与之对应的commit hash值
Git分支
分支当前的指针指向最近一次commit的节点。通过谁创建的分支,就沿用谁的指针。
注:未被放入代码库的文件会在分支切换时被抛弃,造成严重后果。
分支的合并
分支的合并有两种方式,merge和rebase。
相同点:都是从一个分支获取并合并到当前分支。
merge:自动创建一个新的commit,如果遇到冲突,仅需要修改后重新commit。
每次都记录了真实详细的commit,但是在commit频繁的时候,会看到分支比较乱
rebase:找公共的节点,直接合并之前commit历史
这样能得到简洁的分支发展历史,去掉了merge commit。但是如果合并时出现了问题,没有留下痕迹,不好定位
最好不要在公共分支上使用rebase,如果前后基本上不会有别人改动你的分支,那么推荐rebase
分支的冲突
冲突是从合并的时候产生的。git分支的合并,其实就是tree和tree的合并。我们在feature/dev上执行git merge master时。git会先找到这两个分支是从哪个指针创建出来的,称之为“merge base”。然后检查这两次的tree是否一致,如果不一致说明一定有文件发生了修改。接下来,对于某一个文件来说,分几种情况:
文件在节点6,节点3,merge base中的hash值都相同。说明没有被修改过。不会有冲突。
文件在节点6和merge base或者节点3和merge base的hash值相同时,此时直接更新文件的变化。
文件在节点6,merge request,master上的hash值都不同,冲突就产生
版本的回滚
如果想要版本回退,就离不开reset和revert
revert,将回退到上一个commit的版本
reset
git reset分为三种模式:
soft
mixed
hard
git reset --soft commit的hash值 会保留工作目录,
并把指定的commit节点与当前分支的差异都存入暂存区。
也就是说,没有被commit的代码也能够保留下来
代码暂存
当我们在当前分支工作时,不得已需要切换到其他分支处理事情而不想commit时
(如果commit多了,会污染log),可以使用git stash 将那些数据都暂存到Git提供的栈中
git stash
暂存修改过的代码,保存在Git栈中,然后将工作区还原成上一次commit的内容
git stash list
显示之前压栈的所有记录
git stash clear
清空Git栈。
git stash apply
从Git栈中读取上一次暂存的那些代码,恢复工作区
附件列表
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律